Fausto,
Here's some code I wrote to work around this limitation:
* Program...........: Copy2xls.prg
* Author............: Daniel Gramunt
* Created...........: 11.10.2000 17:25:06
*) Description.......: Wrapper to the native COPY TO TYPE XL5 command in order to handle the
*) : VFP limitation of max. 16'383 records. If the number of records exceed
*) : this limitation, we COPY TO TYPE FOX2X and simply SaveAs(
)
*) : using Automation.
*) :
*) : Assumes that MS Excel (Excel 97 or higher) is installed on the
*) : user's machine.
*) :
*) : Returns the number of exported records if successful
*) : otherwise -1 = 1st parameter missing or wrong type
*) : -2 = no table open in current workarea
*) : -3 = number of max. Excel rows exceeded
*) :
* Calling Samples...: Copy2Xls("c:\temp\bidon.xls")
* Parameter List....: tcExcelFile - Path\Filename of the Excel file to be created
* : [tnRecords] - optional.
* : For testing, benchmarking and debugging pass
* : in which case we create a dummy cursor with
* Major change list.: 26.10.2000: COPY TO FOX2X and SaveAs() instead of
* : "assembling" individual Excel files.
* : Thanks to an idea from Çetin Basöz on th UT
*--------------------------------------------------------------------------------------------------
LPARAMETER tcExcelFile, tnRecords
*-- check parameters ------------------------------------------------------------------------------
IF VARTYPE(tcExcelFile) <> "C"
??CHR(7)
WAIT WINDOW NOWAIT "Parameter : Parameter missing or wrong type (Expecting 'C')"
RETURN -1
ENDIF
*-- for testing, benchmarking and debugging you can pass in which case
*-- we create a dummy cursor with
LOCAL lnSelect, i, lcAlias, lnStart, lnRecords, lnFields, lnRetVal, lcTempDbfFile, loXls
lnSelect = SELECT()
IF VARTYPE(tnRecords) = "N" AND tnRecords > 0
*-- create dummy cursor for testing
CREATE CURSOR Copy2Xls (cText C(6), nNumeric N(15,3), lBoolean L, dDate D)
*-- insert some data
FOR i = 1 TO tnRecords
INSERT INTO Copy2Xls VALUES(PADL(i, 6, "0"), i, IIF(MOD(i,2)=0,.t.,.f.), DATE()+i )
ENDFOR &&* i = 1 TO tnRecords
ENDIF
lcAlias = ALIAS()
IF EMPTY(lcAlias)
??CHR(7)
WAIT WINDOW NOWAIT "No table is open in the current workarea"
RETURN -2
ENDIF
lnStart = SECONDS()
#DEFINE cnXlsRecordLimitation 16383
#DEFINE cnXlsMaxNumberOfRows 65536 - 1
lnRecords = RECCOUNT()
lnFields = FCOUNT()
*-- check if number of records exceed VFP limitation
IF lnRecords <= cnXlsRecordLimitation
*-- we don't mess around if we don't exceed the limit and
*-- simply perform the copy
COPY TO (tcExcelFile) TYPE XL5
lnRetVal = _TALLY
ELSE
IF lnRecords > cnXlsMaxNumberOfRows
*MESSAGEBOX("Number of records (" + ;
ALLTRIM(TRANSFORM(lnRecords, "999,999,999")) +;
") exceed max. number of Excel rows (" -;
ALLTRIM(TRANSFORM(cnXlsMaxNumberOfRows, "999,999,999"))+;
"). No data copied!", 16)
lnRetVal = -3
ELSE
lcTempDbfFile = AddBs(SYS(2023)) + SYS(3) + ".DBF"
*-- we copy the data to a DBF III file that Excel can natively read
COPY TO (lcTempDbfFile) TYPE FOX2X
loXls = CREATEOBJECT("excel.application")
loXls.DisplayAlerts = .f. && avoid confirmation messages from excel (similar to SET SAFETY)
#DEFINE xlWorkbookNormal -4143 && used by SaveAs() to save in current version
*-- open file
loXLS.Application.Workbooks.Open(lcTempDbfFile)
*-- save Excel file
loXLS.ActiveSheet.saveAs(tcExcelFile, xlWorkbookNormal)
*-- close Excel
loXls.application.quit()
lnRetVal = RECCOUNT(lcAlias)
*-- delete temp DBF file
IF FILE(lcTempDbfFile)
DELETE FILE (lcTempDbfFile)
ENDIF
ENDIF
ENDIF
IF VARTYPE(tnRecords) = "N" AND tnRecords > 0
*-- close temp cursor
IF USED("Copy2Xls")
USE IN Copy2Xls
ENDIF
*-- display runtime
?"Runtime: ", SECONDS() - lnStart, " seconds!"
ENDIF
SELECT (lnSelect)
RETURN lnRetVal
Daniel