PDA

View Full Version : How to put Down Arrow into clipboard



jbellies
22-10-2007, 06:28
Lines in the text clipboard are delineated by $crlf.
I want to change those to DownArrow so that
an old spreadsheet program will read the numbers
(or whatever other data) properly.

I've fooled around with this, no luck yet. I have
a feeling that I will have to create a non-text clipboard.

TIA

Jonathan Berry

ErosOlmi
22-10-2007, 06:44
Ciao Jonathan.

DownArrow is usually interpreted by the application, is not something the same in every program. Usually $TAB is used for columns separators and $CRLF for lines but this can vary a lot from application to application.
If you are able to identify how to setup text for your application to understand the down arrow, it is possible to arrange clipboard. Otherwise, as you stated, there can me other formats.
thinBasic for the moment has 2 functions working with clipboard: ClipBoard_GetText (http://www.thinbasic.com/public/products/thinBasic/help/html/clipboard_gettext.htm), ClipBoard_SetText (http://www.thinbasic.com/public/products/thinBasic/help/html/clipboard_settext.htm). But we can try to develop some other if needed.

ANother option is to "drive" your application using SendKey (http://www.thinbasic.com/public/products/thinBasic/help/html/sendkeys.htm) but this a different approach.

If you can give us a little more info on the application, maybe someone here can help more. If your application is a spreadsheet, maybe it can read excel files, old format as BIFF one can be created by thinBasic. Sorry, I'm just gessing. Let us know.

Ciao and wellcome
Eros

Michael Hartlef
22-10-2007, 10:50
Would it not be possible to read the file byte wise and and copy the content into a String? Ofcourse, when you read a CR or LF you convert it to the char you need. After reading the file, copy the string to the clipboard.

Michael Clease
22-10-2007, 14:27
if you look at the output with a hex editor you will see that the output is seperated with chr$(29) down arrow.



USES "FILE"

DIM sMsg AS STRING VALUE ""
DIM sOut AS STRING VALUE ""
DIM sInp AS STRING VALUE ""

sMsg += "Text line 1" + $CRLF
sMsg += "Text line 2" + $CRLF
sMsg += "Text line 3" + $CRLF
sMsg += "Text line 4" + $CRLF

sOut = REMOVE$(sMsg, ANY CHR$(10)) ' strip Line feed(s)
sOut = REPLACE$(sOut, ANY CHR$(13), CHR$(29)) ' replace carriage return(s)

' This is to check that the clipboard doesnt message with the string
ClipBoard_SetText( sOut)
sInp = ClipBoard_GetText

' save output so we can look at the results
FILE_SAVE("test.txt", sInp)

Petr Schreiber
22-10-2007, 15:34
Hi,

down arrow is quite weird symbol, I have found that it can be CHR$(25) or CHR$(31) too, according to various sources.
So it could be:



sOut = REPLACE$( sOut, $CRLF, WITH CHR$(25) )

or


sOut = REPLACE$( sOut, $CRLF, WITH CHR$(31) )



Bye,
Petr

Michael Clease
22-10-2007, 15:44
i was using ascii code dec 29 = Group seperator


If you use the ANY option, within sMainString, each occurrence of each character in sMatchString will be replaced with the corresponding character in sNewString.

In this case, sMatchString and sNewString must be the same length, because there is a one-to-one correspondence between their characters.

Petr Schreiber
22-10-2007, 16:10
Hi Abraxas,

I think "mine" syntax should be valid too.
To replace single character with other one, I think you do not need ANY, because it is change 1:1.

See different samples:


dim sString as string = "My dummy text ABCD"

' -- Replaces word "ABCD" with "1"
' -- ( "ABCD" -> "1" )
msgbox 0, replace$( sString, "ABCD", "1")

' -- Replaces character with mask
' -- ( "A" -> "1" )
msgbox 0, replace$( sString, "A", "1")

' -- Replaces any character from word "ABCD" with character on corresponding position in mask
' -- ( "A" -> "1", "B" -> "2", "C" -> "3", "D" -> "4" )
msgbox 0, replace$( sString, ANY "ABCD", "1234")

' -- Replaces any character from word "ABCD" with "1"
' -- ( "A" -> "1", "B" -> "1", "C" -> "1", "D" -> "1" )
msgbox 0, replace$( sString, ANY "ABCD", with "1")

' -- Replaces any character from word "ABCD" with word "1234"
' -- ( "A" -> "1234", "B" -> "1234", "C" -> "1234", "D" -> "1234" )
msgbox 0, replace$( sString, ANY "ABCD", with "1234")


This are just details, I know :-X,
Petr

jbellies
22-10-2007, 19:33
Thanks for all the suggestions. So far, no luck. The program to which I am exporting is called "qubecalc", a 64x64x64 DOS-era spreadsheet. The purpose is just to gather a column of numbers from a text file and quickly export them to the spreadsheet. For example, I might want their sum.

Here is the script, waiting for a magic statement to replace
all the commented-out attempts to replicate a down-arrow.


uses "OS"

dim clip as string = "empty"
dim newclip as string = "empty"
clip = ClipBoard_GetText

'newclip = replace$ (clip, $crlf, chr$ (&hE0, &h50) ) 'produces 892ąP211ąP254ąP100
'newclip = replace$ (clip, $crlf, chr$ (0, 40) ) ' nope
'newclip = replace$ (clip, $crlf, chr$ (25) ) ' qubecalc shows it as y
'newclip = replace$ (clip, $crlf, chr$ (31) ) ' qubecalc shows it as underline
'newclip = replace$ (clip, $crlf, chr$ (29) ) ' qubecalc shows it as ]

msgbox (, newclip) ' what goes back to the clipboard.

ClipBoard_SetText( newclip)

ErosOlmi
22-10-2007, 22:15
Because now we know it is a DOS application and because I do not know if QubeCalc is able to open text files or other file format, I imagine the only way is to use SENDKEYS to interface with DOS keyboard buffer filling with the needed keys. Here it is a sample script that interface using SENDKEYS functionality (it simulates user keystrokes). I downlaoded a demo version of QUBECALC and it seems working fine.

In case you need to load a text file and send data to it, please let me know and I will write a sample code to do that job too.

Ciao
Eros


uses "UI" '---Load user interface module

dim sTitleToFind as string value "...\QUBECALC.COM..." '---This is the string to find in window caption
DIM whndl AS dword
dim Counter as long

'---Find QUBECALC window ...
whndl = win_FindByTitle(sTitleToFind)

'---If not found ...
IF whndl = 0 THEN
msgbox 0, _
"Not able to find QUBECALC window." & $crlf & _
"Please be sure QUBECALC window is opened and " & $CRLF & _
"ready to receive input before executing this script."
else
'---If you are here, cirrect window was found
msgbox 0, "Found at " & whndl

'---Set QUBECALC window as foreground window (give it current focus)
WIN_SETFOREGROUND(whndl)

'---And now do what you prefer simulating user keystrokes
'---Pay attention to give some time to DOS application to perform requested operation
' giving SENDKEY some sleep time. 100 to 300 mSecs seems ok. Make your tests
sendkeys("{home}", 100) '---Go home

For counter = 1 to 10
sendkeys("Counter " & Counter & "{right}123{right}456{down}{left}{left}", 200) '
next

sendkeys("{home}", 100)
sendkeys("{right 4}", 300)
For counter = 1 to 20
sendkeys(format$(Counter * 10) & "{down}", 100)
next

msgbox 0, "All done. Bye"
END IF

ErosOlmi
23-10-2007, 11:37
A little more complex scripts simulating a real string buffer (possibly loaded from a file) and automatically parsed by row/colums. Than use SENDKEYS to send keystrokes to application.

Hope it can help.
Eros



uses "UI" '---Load user interface module
uses "File" '---Load file module

dim sTitleToFind as string value "...\QUBECALC.COM..." '---This is the string to find in window caption
'dim sTitleToFind as string value "Microsoft Excel - ..."
DIM whndl AS dword
dim Counter as long


'---Find QUBECALC window ...
whndl = win_FindByTitle(sTitleToFind)

'---If not found ...
IF whndl = 0 THEN
msgbox 0, _
"Not able to find QUBECALC window." & $crlf & _
"Please be sure QUBECALC window is opened and " & $CRLF & _
"ready to receive input before executing this script."
else
DoTheJob(wHndl)
END IF

'------------------------------------------------
' The real working function
'------------------------------------------------
function DoTheJob(hWnd as long) as long
'------------------------------------------------
dim sBuffer as string
dim cSep as string '---Indicate columns separator
dim lSep as string '---Indicate lines separator
dim nLines as long
dim nCols as long
dim CountLines as long
dim CountCols as long
dim Sequence as long

dim MaxLines as long = 40
dim MaxCols as long = 10

'---Columns separator. Adjust as needed
cSep = $TAB

'---Line separator. Adjust as needed
lSep = $CRLF

'---sBuffer will be used to simulate an input text file.
' If a text file is available, the following few lines of code
' Can be substituted by
' sBuffer = FILE_LOAD(TextFileName)
'---
randomize
for CountLines = 1 to MaxLines
for CountCols = 1 to MaxCols
incr Sequence
sBuffer += format$(Sequence) & iif$(CountCols < MaxCols, cSep, "")
next
sBuffer += iif$(CountLines < MaxLines, lSep, "")
next

'---Set QUBECALC window as foreground window (give it current focus)
WIN_SETFOREGROUND(whndl)


'---Ok, at this point we should have a string buffer loaded
'---We need to determine how many colums and lines the buffer have
dim sMatrix() as string
nLines = PARSE(sBuffer, sMatrix, lSep, cSep)
nCols = ubound(sMatrix(2))

'---Start the operations.
'---IMPORTANT: adjust correct timeout depending on window response

sendkeys("{home}", 100)

for CountLines = 1 to nLines
for CountCols = 1 to nCols
sendkeys(sMatrix(CountLines, CountCols) & iif$(CountCols < nCols, "{right}", ""), 20)
next
if CountLines < nLines then sendkeys("{down}{left " & nCols & "}", 20)
next
sendkeys("{enter}", 50)

'---Operation finished

end function

jbellies
23-10-2007, 18:50
Thanks, Eros!

The answer in one word is "SENDKEYS".

Here is code, based upon both of ours, to do the narrowly-defined
task that I had in mind.



uses "UI" '---Load user interface module
uses "OS"

'testqubejb.tbasic - Jonathan Berry 2007 hereby released into the public domain
'UI code by Eros Olmi
'exports a column (of numbers) from the clipboard to qubecalc, started from the
'command prompt with a batch file qu [filename]. So look for "qu " in the win handle
'runs rather more slowly than the sendkeys-only program sample of Eros Olmi
'but faster and less error prone than retyping the numbers !!!

dim clip as string = "empty"
dim newclip as string = "empty"
dim pars as integer
dim i as integer

clip = ClipBoard_GetText

dim sTitleToFind as string value "...qu ..." '"...\QUBECALC.COM..." '---This is the string to find in window caption
DIM whndl AS dword
dim Counter as long

'---Find QUBECALC window ...
whndl = win_FindByTitle(sTitleToFind)

'---If not found ...
IF whndl = 0 THEN
msgbox 0, _
"Not able to find QUBECALC window." & $crlf & _
"Please be sure QUBECALC window is opened and " & $CRLF & _
"ready to receive input before executing this script."
else
'---If you are here, correct window was found
msgbox 0, "Found at " & whndl

'---Set QUBECALC window as foreground window (give it current focus)
WIN_SETFOREGROUND(whndl)

'---Pay attention to give some time to DOS application to perform requested operation
' giving SENDKEY some sleep time. 100 to 300 mSecs seems ok. Make your tests

pars = parsecount (clip, $crlf)
for i = 1 to pars
newclip = parse$ (clip, $crlf, i)
newclip = remove$ (newclip, ANY "$, ") & "{down}"
sendkeys (newclip, 10)
' newclip = remove$ (newclip, ANY "$, ")
' sendkeys (newclip & "{down}", 10)
' using 10. It's slow no matter what number one uses. But slightly faster than sendkeys (newclip & "{down}", 10)
next ' note next i produces an error message!

msgbox 0, "All done. Bye"
END IF

ErosOlmi
23-10-2007, 19:54
The answer in one word is "SENDKEYS".

Yes, it is very powerful



dim clip as string = "empty"

Strange initialization here, unless it is exactly what you want ;)



next ' note next i produces an error message!

In many BASIC languages (especially old ones) it is necessary to repeat the name of the variable controlling FOR/NEXT loops. thinBasic keep track of all FOR/NEXT nested loops so it is able to increment/decrement the relevant variable when a NEXT is encountered.

I'm happy I could help.
Ciao
Eros