Excel
Excel
Excel Automation
(Updated: 2007.08.24 01:47:10 PM)
Namespace: VFP
Edit -Find- Recent Changes Categories Road Map [A-F] [G-P] [Q-Z] New Topic Home
Go
Search:
For clarity's sake, the full object hierarchy is used for each command. Using a 'With
oExcel' will tend to make your code more readable.
Connecting to Excel
We'll assume throughout this page that you named your Excel object oExcel and your
workbook oWorkbook.
oExcel = CreateObject("Excel.Application")
if vartype(oExcel) != "O"
* could not instantiate Excel object
* show an error message here
return .F.
endif
You can turn off Excel's alerts with the DisplayAlerts property: when set to False, Excel
automatically chooses the default answer to any message:
oExcel.DisplayAlerts = .F.
oWorkbook.Close() && Unsaved changes will be discarded
oExcel.DisplayAlerts = .T.
Saving a workbook as an Excel 97/2003 spreadsheet from Excel 2007
Using SaveAs while automating Excel 2007 creates a 2007 style workbook with an XLS
extension (regardless of compatibility settings) unless the file format is specified:
if val(oExcel.Version) > 11
oWorkbook.SaveAs("C:\temp\foobar.xls", 56) && xlExcel8
else
oWorkbook.SaveAs("C:\temp\foobar.xls")
endif
Controlling visibility
If the Excel window is not visible it is harder for the user to interact with Excel. This
makes it slightly safer for your automation as the user is less likely to issue commands in
the middle of your automation.
oExcel.visible = .T.
oExcel.visible = .F.
Controlling Interaction
Also, if it is preferred that Excel be seen during automation set these two properties to .F.
oExcel.Application.UserControl=.F.
oExcel.Application.Interactive=.F.
After completing automation, return their value to .T. to allow the user to start interaction
oExcel.Application.UserControl=.T.
oExcel.Application.Interactive=.T.
or
oExcel.Range("B6").Select()
oExcel.Selection.font.colorindex = 3 && red
oExcel.Selection.font.bold = .t.
-- David Fung
Or if you have a pre-formatted template (.XLS or .XLT) that you want to paste into. Note
that this method will not handle Memo fields.
_VFP.DataToClip(,,3) && current table onto the clipboard,
delimited with tab
oExcel.Range("A1").Select
oExcel.ActiveSheet.Paste() && from clipboard. since
delimited with tab, store data into columns
-- David Fung
Closing Excel
You'll still need to handle closing questions like saving changes and file format changes.
And you'll need to release your oExcel object
oExcel.quit()
-- David Fung
-- Stuart Dunkeld
* then open excel and make the data look good, like this
oExcel = CreateObject("Excel.Application")
if vartype(oExcel) != "O"
* could not instantiate Excel object
* show an error message here
return .F.
endif
oExcelApp = oExcel.Application
oExcelApp.WindowState = xlMaximized
* find address of last occupied cell
lcLastCell = oExcel.ActiveCell.SpecialCells(xlLastCell).Address()
* save Excel file in new Excel format (COPY TO XLS uses old format)
oWorkbook.Save()
-- Alex Feldstein
Sometimes the Last Cell is not up-to-date after deleting a row in Excel,
Calling ActiveSheet.UsedRange after deleting a row will keep Last Cell
up-to-date.
loExcel = createobject('Excel.Application')
loExcel.Workbooks.Open(tcFile)
loExcel.Rows("1").Delete(xlUp)
lnLastRowIncorrect = loExcel.Cells.SpecialCells(xlCellTypeLastCell).Row
loExcel.ActiveSheet.UsedRange && add this line
lnLastRowCorrect = loExcel.Cells.SpecialCells(xlCellTypeLastCell).Row
-- David Fung
etc. These commands are version dependant directly within VFP themselve. You
immediately lose data with these commands.
-The number of rows you can copy is limited for example (VFP5 copied 16384 max
while VFP9 copies 65536 max, but as new Excel versions come into market those limits
are not sufficient anymore).
-Memo fields are immediately dropped as with any 'copy to' command
Copy to myExcel.xls type fox2x && actually creating a dBaseIII compatible file. Excel
recognizes internally
Copy to myExcel.csv type csv && CSV files are natively recognized
Both fail to transfer memo fields and CSV might have problems with datatypes converted
correctly (mostly with date fields) but in general are better than Data To Clip() and
'copy ... type xls'.
Similar to Data To Clip() you can copy to a tab delimited file, read it into clipboard with
FileToStr() and pasteSpecial() in Excel. Works better than Data To Clip() but it again falls
short of transferring memo fields.
Excel (especially newer versions) also recognizes XML and HTM ( table tags ).
My best preferance is to transfer data using ADO instead. Passing with ADO uses Excel's
own VBA commands to 'paste' the data. Here is a sample sending data to Excel and
putting data starting at A10:
LOCAL oExcel
oExcel = Createobject("Excel.Application")
With oExcel
.WorkBooks.Add
.Visible = .T.
VFP2Excel(_samples+'data\testdata.dbc','select * from
employee',.ActiveSheet.Range('A10'))
Endwith
function VFP2Excel
lparameters tcDataSource, tcSQL, toRange
Local loConn As AdoDB.Connection, ;
loRS As AdoDB.Recordset,;
ix
loConn = Createobject("Adodb.connection")
loConn.ConnectionString = "Provider=VFPOLEDB;Data
Source="+m.tcDataSource
loConn.Open()
loRS = loConn.Execute(m.tcSQL)
Note that .Visible = .T. is very early in code just after adding the workbook. Having that
"later after you're done with populating cells males things faster" is a myth. Surprisingly
having it early in code makes your code faster in many cases.
My suggestions:
Working with Excel means you're doing COM calls using VBA which by nature is slow.
Therefore, whenever possible, do things at VFP side and call Excel automation
commands as few as you can. ie:
Instead of this:
for ix = 1 to 5000
for jx=1 to 10
.Cells(m.ix,m.jx).Value = m.ix*100+m.jx
endfor
endfor
Do this:
dimension aExcelData[5000,10]
for ix = 1 to 5000
for jx=1 to 10
aExcelData[m.ix,m.jx] = m.ix*100+m.jx
endfor
endfor
WITH oExcel.ActiveWorkBook.ActiveSheet
.Range(.Cells(1,1), .Cells(5000,10)).Value = GetArrayRef('aExcelData')
endwith
PROCEDURE GetArrayRef(tcArrayName)
RETURN @&tcArrayName
Above code also shows another alternative to transferring data to Excel via array instead
of pasting.
Cetin Basoz
Contributors: Alex Feldstein Tom Cerul Stuart Dunkeld David Fung Cetin Basoz