Can REV create Excel files?
Ken Ray
kray at sonsothunder.com
Sat Mar 3 13:30:52 EST 2007
On Sat, 3 Mar 2007 18:43:33 +0900, Martin Blackman wrote:
> Ken
> I see there's a nice example of writing to Excel on your website using
> vbscript. Is this the sort of thing that might trigger anti-virus
> programs ? I just tried it on 2 machines successfully with no
> anti-virus problems myself.
It depends on the level of sensitivity of the antivirus software. Most
(all?) will not stop all vbscript executions, but look for things like
access to the file system in the code to be run to determine whether to
bring up a warning or not. Since the Excel example is just for
communications with Excel, it is very unlikely that it would trigger
antivirus software (unless there is a generic "Don't allow VBScript
files to run" option in the AV software that's turned on).
> Would you be good enough to expand on that example to setting/getting
> data from named cells or ranges ?
Sure... this is based on modifying the "put ... into tScript" portion
of the SendToXL handler that is described on the Tip page
(http://www.sonsothunder.com/devres/revolution/tips/iac001.htm). The
relevant portion is copied below:
on mouseUp
SendToXL "500","B3"
end mouseUp
on SendToXL pWhat,pCell
put "Dim ObjXL" & cr & \
"Set ObjXL = GetObject(," & q("Excel.Application") & ")" & cr & \
"ObjXL.Range(" & q(pCell) & ").Value =" && q(pWhat) into tScript
-- Put the script into a file on disk
put "C:\VBSTemp.vbs" into tFile
put tScript into url("file:" & tFile)
-- Run the file
set the hideConsoleWindows to true
get shell("cscript.exe //nologo" && tFile)
-- Now, delete the file; best way is to give it 1 second to complete
-- before deleting, so I'll use the "send in " method to
-- do this:
send "delete file" && q(tFile) to me in 1 second
end SendToXL
If you have a named cell, all you need to do is pass in the name of the
cell in the pCell parameter, so you could name a cell "MyNamedCell" and
then execute:
SendToXL "500","MyNamedCell"
To get data from a cell, all you need to do is modify the SendToXL
handler to return a result using WScript.Echo. Here's a "GetFromXL"
handler that will retrieve the data from a specific cell (using A1,
R1C1, or named cell format) - I removed the comments to make it more
compact:
function GetFromXL pCell
put "Dim ObjXL" & cr & \
"Set ObjXL = GetObject(," & q("Excel.Application") & ")" & cr & \
"WScript.Echo ObjXL.Range(" & q(pCell) & ").Value" into tScript
put "C:\VBSTemp.vbs" into tFile
put tScript into url("file:" & tFile)
set the hideConsoleWindows to true
get shell("cscript.exe //nologo" && tFile)
send "delete file" && q(tFile) to me in 1 second
return it
end GetFromXL
So you could do this:
put GetFromXL("MyNamedCell") into tVar -- tVar now has "500" in it
To get or set a multi-cell range requires a bit more work - you
basically need to loop through all the cells in the range, which is
several more lines of VBScript code. Here's a modified "GetFromXL"
function that will do the trick (and still keep backward compatibility):
function GetFromXL pRangeRef
put "Dim ObjXL,tNumRows,tNumCols,tRetVal,tRow,tCol" & cr & \
"Set ObjXL = GetObject(," & q("Excel.Application") & ")" & cr & \
"tNumRows = ObjXL.Range(" & q(pRangeRef) & ").Rows.Count" & cr & \
"tNumCols = ObjXL.Range(" & q(pRangeRef) & ").Columns.Count" into
tScript
put tScript & cr & "For tRow = 1 To tNumRows" & cr & \
"For tCol = 1 to tNumCols" & cr & \
"If tCol <> tNumCols Then" & cr & \
"tRetVal = tRetVal & ObjXL.Range(" & q(pRangeRef) &
").Cells(tRow,tCol).Value & vbTab" & cr & \
"Else" & cr & \
"tRetVal = tRetVal & ObjXL.Range(" & q(pRangeRef) &
").Cells(tRow,tCol).Value & vbCrLf" & cr & \
"End If" & cr & "Next" & cr & "Next" into tScript
put tScript & cr & "tRetVal = Left(tRetVal,Len(tRetVal) - 2)" & cr
& \
"WScript.Echo tRetVal" into tScript
put "C:\VBSTemp.vbs" into tFile
put tScript into url("file:" & tFile)
set the hideConsoleWindows to true
get shell("cscript.exe //nologo" && tFile)
send "delete file" && q(tFile) to me in 1 second
if char -1 of it is CR then delete char -1 of it -- strip any
trailing CR
return it
end GetFromXL
So now you can do any of these:
put GetFromXL("A1:D4") into tTable
put GetFromXL("MyNamedRange") into tTable
put GetFromXL("MyNamedCell") into tCell
put GetFromXL("A1") into tCell
Setting a range is basically the same, but goes in the opposite
direction. Here's a new replacement "SendToXL" handler that will handle
individual cells and ranges in the same way that GetFromXL does above:
on SendToXL pWhat,pRangeRef
-- assumes a tab & CR delimited set of data
set the itemDel to tab
put the number of items of line 1 of pWhat into tNumCols
put the number of lines of pWhat into tNumRows
put "Dim ObjXL,tRetVal,tRow,tCol" & cr & \
"Dim tDataA(" & tNumCols & "," & tNumRows & ")" & cr & \
"Set ObjXL = GetObject(," & q("Excel.Application") & ")" into
tScript
repeat with x = 1 to tNumCols
repeat with y = 1 to tNumRows
put tScript & cr & "tDataA(" & x & "," & y & ") = " & q(item x of
line y of pWhat) into tScript
end repeat
end repeat
put tScript & cr & "For tRow = 1 To" && tNumRows & cr & \
"For tCol = 1 to" && tNumCols & cr & \
"ObjXL.Range(" & q(pRangeRef) & ").Cells(tRow,tCol).Value =
tDataA(tCol,tRow)" & cr & \
"Next" & cr & "Next" into tScript
put "C:\VBSTemp.vbs" into tFile
put tScript into url("file:" & tFile)
set the hideConsoleWindows to true
get shell("cscript.exe //nologo" && tFile)
send "delete file" && q(tFile) to me in 1 second
end SendToXL
So something like:
put "Hello" & tab & "there" & cr & "From" & tab & "Ken" into tData
SendToXL tData,"A1:B2"
Have fun!
Ken Ray
Sons of Thunder Software, Inc.
Email: kray at sonsothunder.com
Web Site: http://www.sonsothunder.com/
More information about the use-livecode
mailing list