microsoft_ visual foxpro - excel import

7

Click here to load reader

Upload: lakshmanan-sivalingam

Post on 28-Oct-2015

140 views

Category:

Documents


3 download

DESCRIPTION

Microsoft_ Visual FoxPro - Excel Import

TRANSCRIPT

Page 1: Microsoft_ Visual FoxPro - Excel Import

8/16/13 Microsoft: Visual FoxPro - Excel Import

www.tek-tips.com/viewthread.cfm?qid=1654224 1/7

Smart questionsSmart answersSmart people

Go Find A Forum Go

JoinDirectorySearchTell A FriendWhitepapersJobs

Home > Forums > Programmers > DBMS Packages > Microsoft: Visual FoxPro Forum

Excel Import thread184-1654224

seckner (Programmer) 7 Jul11

15:53

Could someone show me a drop dead example of pulling rows out of Excel and into VFP9?

We get a spreadsheet by email several times a day and I've been able to importing them. Well, they have changed the format with about 5 lines of"Header Junk" and the data now starts on row 6 vs row 1. I know I need to use Automation but I don't really know how. A start would be great help!

TamarGranor (Programmer) 7 Jul11

16:20

Something along these lines:

CODE

LOCAL oXL, oBook, oSheet

oXL = CREATEOBJECT("Excel.Application")oBook = oXL.Workbooks.Open("Your file with path")

oSheet = oBook.Worksheets[1]

nLastRow = oSheet.UsedRows.Count

* Assumes data starts in row 1, col 1. Adjust as necessaryFOR nRow = 1 TO m.nLastRow cItem1 = oSheet.Cells(m.nRow, 1) cItem2 = oSheet.Cells(m.nRow, 2) * etc.

INSERT INTO YourTable ; VALUES (m.cItem, m.cItem2)ENDFOR

oBook.Close()oXL.Quit()

Tamar

seckner (Programmer) 7 Jul11

16:37

Wow - Thank you! Small problem, again it's my lack of knowledge - when I try to run this I get an error stating that USEDROWS does not evaluate to an

Read More Threads Like This One

Share This

Page 2: Microsoft_ Visual FoxPro - Excel Import

8/16/13 Microsoft: Visual FoxPro - Excel Import

www.tek-tips.com/viewthread.cfm?qid=1654224 2/7

object. I apologize but I don't know where to go from here.

TamarGranor (Programmer) 8 Jul11

16:31

That's because I got it wrong, typing off the top of my head. Try

UsedRange.Rows

where I had UsedRows.

Tamar

Nifrabar (Programmer) 10Aug11

7:30

fwiwI once found this info somewhere on the www. so credits for Alex Feldstein, Tom Cerul, Stuart Dunkeld, David Fung and Cetin Basoz!

It might help making a start with excel-automationCODE

Wide 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 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 ExcelWe'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

--------------------------------------------------------------------------------Constants for ExcelExcel Constants documents the constants that Excel's macros use (xlThis, xlThat etc)2007/08/30 Mike Mohr - Excel 2003 Constants MSDN Library2007/08/30 Mike Mohr - Excel 2007 (office 12) Constants MSDN Library --------------------------------------------------------------------------------Opening an existing XLS

oWorkbook = oExcel.Application.Workbooks.Open("C:\temp\test.xls")

Creating a blank workbook:

oWorkbook = oExcel.Application.Workbooks.Add()

Creating a new workbook based on a template:

oWorkbook = oExcel.Application.Workbooks.Add("C:\temp\template.xlt")

-------------------------------------------------------------------------------- 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 discardedoExcel.DisplayAlerts = .T.-------------------------------------------------------------------------------- Saving a workbook as an Excel 97/2003 spreadsheet from Excel 2007Using SaveAs while automating Excel 2007 creates a 2007 style workbook with an XLS extension (regardless of compatibility settings) unless the file format is specified:

Page 3: Microsoft_ Visual FoxPro - Excel Import

8/16/13 Microsoft: Visual FoxPro - Excel Import

www.tek-tips.com/viewthread.cfm?qid=1654224 3/7

if val(oExcel.Version) > 11 oWorkbook.SaveAs("C:\temp\foobar.xls", 56) && xlExcel8else oWorkbook.SaveAs("C:\temp\foobar.xls")endif

--------------------------------------------------------------------------------Controlling visibilityIf 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 InteractionAlso, 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.

--------------------------------------------------------------------------------Storing data to a cell

oExcel.Range("b2").Value = "Hello world"

-------------------------------------------------------------------------------- Set the font color and style

oExcel.Range("B6").font.bold = .t.oExcel.Range("B6").font.colorindex = 3 && red

or

oExcel.Range("B6").Select()oExcel.Selection.font.colorindex = 3 && redoExcel.Selection.font.bold = .t.

-- David Fung --------------------------------------------------------------------------------Getting data into ExcelAssuming your table is selected. First the easy way. You can make a new file in an old Excel format which all version should be able to read.

copy to c:\mytable.xls type xl5

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 taboExcel.Range("A1").SelectoExcel.ActiveSheet.Paste() && from clipboard. since delimited with tab, store data into columns

--------------------------------------------------------------------------------Selecting a range using the Cells collection

oExcel.Range(oExcel.cells(1, 1), oExcel.Cells(3.3)).Select

--------------------------------------------------------------------------------Resize all columns

oExcel.ActiveSheet.UsedRange.EntireColumn.Autofit

-------------------------------------------------------------------------------- Insert two rows before the first row

oExcel.Rows("1:2").Insert(-4121) && xlDown

-- David Fung --------------------------------------------------------------------------------

Page 4: Microsoft_ Visual FoxPro - Excel Import

8/16/13 Microsoft: Visual FoxPro - Excel Import

www.tek-tips.com/viewthread.cfm?qid=1654224 4/7

Closing ExcelYou'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()

--------------------------------------------------------------------------------Closing Excel with all changes discarded - no question asked

oExcel.DisplayAlerts = .F.oExcel.ActiveWindow.Close(.f.) && assuming only one active windowoExcel.quit()

-- David Fung --------------------------------------------------------------------------------Iterate through Excel's Worksheets

For i=1 To oExcel.ActiveWorkbook.Sheets.Count ? oExcel.ActiveWorkbook.Sheets(i).NameEndfor

--------------------------------------------------------------------------------Finding text in ExcelSearching for "Tax"

oExcel.Range("A1:H250").Find("Tax").Select && simple default search* Alternately* Range.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)oExcel.Range("A1:H250").Find("Tax", oExcel.ActiveCell, -4123, 1).Select

Range("A1:H250") specifies that we're searching columns A to H (inclusive) and rows 1-250.oExcel.ActiveCell is where to start searching, and -4123 is the constant for xlFormulas. I theorize that this means 'if there is a formula, search its code rather than its output.' 1 is the constant for xlWhole, meaning match against all the text in the cell. You could swap in 2 to get partial matches.-- Tom Cerul

You have to be careful when specifying the extra parameters to Find as they persist between searches, as specified in the Excel documentation:

The settings for LookIn, LookAt, SearchOrder, and MatchByte are saved each time you use this method. If you don't specify values for these arguments the next time you call the method, the saved values are used. Setting these arguments changes the settings in the Find dialog box, and changing the settings in the Find dialog box changes the saved values that are used if you omit the arguments. To avoid problems, set these arguments explicitly each time you use this method.

-- Stuart Dunkeld --------------------------------------------------------------------------------Developing new codeSometimes the easiest way to figure out how to code an automation routine is this: open Excel, tell it to record a macro, do the task you want to automate. Stop the recording and look at the code that it generated. --------------------------------------------------------------------------------Putting it all together, a runnable example

First, COPY TO all fields (or some) in Excel Format

#define xlLastCell 11#define xlMaximized -4137#define xlRangeAutoformatClassic2 2#define xlPortrait 1

use MyTable && or SELECT * INTO MyCursor

cFileName = "MyXLSFile" && or whatever, including path*copy to (cFileName) fields (cFields) TYPE xlscopy to (cFileName) TYPE xls

* then open excel and make the data look good, like thisoExcel = CreateObject("Excel.Application")if vartype(oExcel) != "O" * could not instantiate Excel object * show an error message here return .F.endif

* make excel visible during development*oExcel.visible = .T.

* open the workbook you just createdoExcel.SheetsInNewWorkBook = 1oWorkbook = oExcel.Workbooks.Open(cFileName)

Page 5: Microsoft_ Visual FoxPro - Excel Import

8/16/13 Microsoft: Visual FoxPro - Excel Import

www.tek-tips.com/viewthread.cfm?qid=1654224 5/7

* rename the Sheet to whatever you likeoActiveSheet = oExcel.ActiveSheetoActiveSheet.Name = "MyData"

oExcelApp = oExcel.ApplicationoExcelApp.WindowState = xlMaximized

* find address of last occupied celllcLastCell = oExcel.ActiveCell.SpecialCells(xlLastCell).Address()

* resize all columnslnMarker1 = at("$",lcLastCell,1) && i.e. 1 when lcLastCell = "$AF$105"lnMarker2 = at("$",lcLastCell,2) && i.e. 4 when lcLastCell = "$AF$105"lnStartPos = lnMarker1 + 1lnStrLen = lnMarker2 - lnStartPosoExcel.Columns("A:" + substr ; (lcLastCell,lnStartPos,lnStrLen)).EntireColumn.AutoFit

* you can even add a nice autoformatoExcel.Range("A" + alltrim(str(nTOPBLANKROWS+1)) + ":" + lcLastCell).SelectoExcel.Selection.AutoFormat(xlRangeAutoformatClassic2,.t.,.t.,.t.,.t.,.t.,.t.)

* set Excel Print AreaoActiveSheet.PageSetup.PrintArea = "$A$1:" + lcLastCell

* define printed page footerWith loActiveSheet.PageSetup *.LeftHeader = "" *.CenterHeader = "" *.RightHeader = "" .LeftFooter = "&BMy Footer goes here&B" .CenterFooter = "&D" .RightFooter = "Page &P" *.PrintHeadings = .F. .PrintGridlines = .F. .CenterHorizontally = .T. .CenterVertically = .F. .Orientation = xlPortraitendwith

* save Excel file in new Excel format (COPY TO XLS uses old format)oWorkbook.Save()

* display finished product to the useroExcel.visible = .T.

-- 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).RowloExcel.ActiveSheet.UsedRange && add this linelnLastRowCorrect = loExcel.Cells.SpecialCells(xlCellTypeLastCell).Row

-- David Fung

Having worked with excel a lot a few notes:Office applications are not as much backward compatible as VFP is. For that reason I suggest not to use VFP's direct Excel related commands like:

copy to myExcel type xls && or xl5,xl8...import ... type xl8

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

Data To Clip() - Do not use Data To Clip() for Excel transfers.

Page 6: Microsoft_ Visual FoxPro - Excel Import

8/16/13 Microsoft: Visual FoxPro - Excel Import

www.tek-tips.com/viewthread.cfm?qid=1654224 6/7

-You lose Memo fields but worse you get a transform() version of memo fields.-You're limited on rowcount that you can transfer with this method. There is no exact number and sounds like related with Excel version + available memory. It's possible you end with much fewer rows than you could transfer using 'copy to'. Likely you'd get unpredictable exceptions.

Instead you can use:

Copy to myExcel.xls type fox2x && actually creating a dBaseIII compatible file. Excel recognizes internallyCopy 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 oExceloExcel = 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)

FOR ix=1 TO loRS.Fields.Count toRange.Offset(0,m.ix-1).Value = PROPER(loRs.Fields(m.ix-1).Name) toRange.Offset(0,m.ix-1).Font.Bold = .t. ENDFOR toRange.Offset(1,0).CopyFromRecordSet( loRS ) loRs.Close loConn.Close

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 endforendfor

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 endforendfor

WITH oExcel.ActiveWorkBook.ActiveSheet .Range(.Cells(1,1), .Cells(5000,10)).Value = GetArrayRef('aExcelData')endwith

PROCEDURE GetArrayRef(tcArrayName)RETURN @&tcArrayName

Page 7: Microsoft_ Visual FoxPro - Excel Import

8/16/13 Microsoft: Visual FoxPro - Excel Import

www.tek-tips.com/viewthread.cfm?qid=1654224 7/7

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

--------------------------------------------------------------------------------Category Code Samples Category Automation

Edit -Find- Recent Changes Categories Road Map [A-F] [G-P] [Q-Z] New Topic Home Search:http://fox.wikis.com - a low-impedance, fat-free Visual Foxpro site. - 2009.06.29 05:15:03 AM EST

-Bart

TamarGranor (Programmer) 11Aug11

15:48

Rather than pasting a whole page from the VFP wiki here, why not just link the page:

http://fox.wikis.com/wc.dll?Wiki~ExcelAutomation~VFP

Tamar

Nifrabar (Programmer) 12Aug11

8:32

Tamar,You are right, but I once copied this information and stored it in my archives without storing the exact source-location as well. So I didnot remember where I took it from but nevertheless I found it worth to share this.-Bart

TamarGranor (Programmer) 12Aug11

16:51

My suggestion is that when you do that, you paste the URL in your archive as well. It's generally considered rude (or worse) to post the full exact text ofanother person's web page.

Also, pages like that one on a Wiki keep getting updated, so there may be more information there now than when you copied it.

Finally, by pointing someone to a page on the VFP Wiki, you introduce them to the tool, one that every VFP developer should know about.

Tamar

Join | Jobs | Advertise | About Us | Contact Us | Site Policies

Copyright © 1998-2013 Tecumseh Group, Inc. All rights reserved.Unauthorized reproduction or linking forbidden without express written permission.

Read More Threads Like This One