La rutina abre un libro de Excel y lo pasa a un cursor tomando la primera fila como los encabezados de las columnas.
LOCAL lcXLSBook AS STRING lcXLSBook = GETFILE('xls, xlsx', 'Archivo:', 'Aceptar', 0, 'Seleccione una hoja de cálculo') IF EMPTY(lcXLSBook) RETURN .F. ENDIF ExcelToCursor(m.lcXLSBook, "xlsResult") SELECT xlsResult BROWSE NOWAIT *!------------------------------------------------------------------------------ *! Procedure : ExcelToCursor *! Parametros: pcSrcFile -> Nombre del libro de excel *! pcCursorName -> Nombre del cursor *!------------------------------------------------------------------------------ PROCEDURE ExcelToCursor(pcSrcFile AS STRING, pcCursorName AS STRING) IF PCOUNT() = 0 RETURN .F. ELSE IF VARTYPE("pcSrcFile")#"C" RETURN .F. ENDIF IF !FILE(pcSrcFile) MESSAGEBOX("Archivo no encontrado", 16) RETURN .F. ENDIF IF VARTYPE("pcCursorName")#"C" RETURN .F. ENDIF ENDIF *** Instanciar MS Excel LOCAL oExcel AS Excel.APPLICATION m.oExcel = CREATEOBJECT("Excel.application") IF VARTYPE(oExcel,.T.)!='O' MESSAGEBOX("No se puede procesar el archivo." ; + CHR(13) + "Microsoft Excel no está instalado en su ordenador.", 16) m.oExcel = NULL RELEASE oExcel RETURN .F. ENDIF *** Abrir archivo de Excel m.oExcel.Workbooks.OPEN(pcSrcFile) m.oExcel.Worksheets(1).ACTIVATE m.oExcel.DisplayAlerts = .F. LOCAL oSheet AS OBJECT m.oSheet = m.oExcel.ActiveSheet LOCAL aExcel(1), laStructure(1) LOCAL lnCol, lnRow, lnSize, lcCol, lcRow, lcValue, lcCmd *** Redimensionar aExcel de acuerdo a las filas y columnas que *** contiene el libro de excel abierto IF EVALUATE("ALEN(aExcel)") # m.oSheet.UsedRange.COLUMNS.COUNT DIMENSION aExcel [1, m.oSheet.UsedRange.Columns.Count] ENDIF m.lnCol = m.oSheet.UsedRange.COLUMNS.COUNT m.lnRow = m.oSheet.UsedRange.ROWS.COUNT *** Pasar los valores del libro de excel *** a la matriz redimensionada aExcel TEXT TO lcCmd TEXTMERGE NOSHOW PRETEXT 1+2 aExcel = m.oExcel.ActiveWorkbook.ActiveSheet.Range(m.oSheet.Cells(1,1), m.oSheet.Cells(<<m.lnRow>>,<<m.lnCol>>)).value ENDTEXT &lcCmd *** Cerrar la instancia MS Excel m.oExcel.QUIT() m.oExcel = NULL RELEASE oExcel, oSheet *** Procedimiento para determinar los tipo de datos por *** columnas y crear la estructura del cursor m.lnRow = ALEN(aExcel,1) m.lnCol = IIF(ALEN(aExcel,2)>0, ALEN(aExcel,2), 1) *** La matriz laStructure bidimensional *** almacena la estructura del cursor *** Columna 1 -> Nombre de la columna *** Columna 2 -> Tipo de datos *** Columna 3 -> Largo *** Columna 4 -> Decimal *** Columna 5 -> Acepta valores null DIMENSION laStructure(m.lnCol,5) FOR i = 1 TO m.lnCol m.lnSize = 1 m.lcCol = LTRIM(STR(i)) laStructure(i,1) = aExcel(1,i) laStructure(i,2) = VARTYPE(aExcel(2,i)) DO CASE CASE laStructure(i,2) = "C" && Character, Memo, Varchar, Varchar (Binary) FOR j = 1 TO m.lnRow m.lcValue = IIF(m.lnCol = 1, TRANSFORM(aExcel(j)), TRANSFORM(aExcel(j,i))) m.lnSize = MAX(m.lnSize, LEN(TRANSFORM(aExcel(j,i)))) IF AT(CHR(13), m.lcValue) > 0 laStructure(i,2) = "M" && Memo ENDIF ENDFOR IF laStructure(i,2) = "C" && Character, Varchar IF lnSize < 10 laStructure(i,3) = 10 ELSE laStructure(i,3) = lnSize ENDIF laStructure(i,4) = 0 ELSE && Memo, Blob laStructure(i,3) = 4 laStructure(i,4) = 0 ENDIF CASE laStructure(i,2) = "D" OR laStructure(i,2) = "T" && Date, DateTime laStructure(i,3) = 8 laStructure(i,4) = 0 CASE laStructure(i,2) = "L" && Logical laStructure(i,3) = 1 laStructure(i,4) = 0 CASE laStructure(i,2) = "N" && Numeric, Float, Double, o Integer laStructure(i,3) = 12 laStructure(i,4) = 2 OTHERWISE ENDCASE laStructure(i,5) = .T. ENDFOR *** Crear el cursor CREATE CURSOR &pcCursorName FROM ARRAY laStructure *** Insertar en el cursor los valores desde aExcel LOCAL lCellValue m.lcRow = "" FOR i = 1 TO m.lnRow FOR j = 1 TO m.lnCol IF !EMPTY(m.lcRow) m.lcRow = m.lcRow + ", " ENDIF lCellValue = EVALUATE([aExcel(i,j)]) DO CASE CASE VARTYPE(lCellValue) = "C" && Character, Memo, Varchar, Varchar (Binary) IF !EMPTY(lCellValue) OR lCellValue # "" m.lcRow = m.lcRow + ['] + EVALUATE([aExcel(i,j)]) + ['] ELSE m.lcRow = m.lcRow + [Null] ENDIF CASE VARTYPE(lCellValue) = "D" OR VARTYPE(lCellValue) = "T" && Date, DateTime m.lcRow = m.lcRow + [{] + EVALUATE([aExcel(i,j)]) + [}] CASE VARTYPE(lCellValue) = "N" && Numeric, Float, Double, o Integer m.lcRow = m.lcRow + ALLTRIM(STR(EVALUATE([aExcel(i,j)]))) OTHERWISE m.lcRow = m.lcRow + EVALUATE([aExcel(i,j)]) ENDCASE ENDFOR IF i > 1 TEXT TO cSQL TEXTMERGE NOSHOW PRETEXT 1+2 Insert Into <<pcCursorName>> Values (<<lcRow>>) ENDTEXT EXECSCRIPT(cSQL) ENDIF m.lcRow = "" ENDFOR *** Liberar variables RELEASE pcSrcFile, laStructure, lnSize, lcValue, lcCmd RELEASE lCellValue, aExcel, lnCol, lnRow, lcCol, lcRow, cSQL, i, j SELECT &pcCursorName GO TOP *** Retornar el cursor RETURN SETRESULTSET(pcCursorName) ENDPROC
Hector Urrutia
Hola, porque al cerrar el libro.xls me pregunta si quiero guardar los cambios? Se puede evitar?
ResponderBorrarPregunta, se puede abrir el libro de excel con "m.oExcel.Workbooks.OPEN(pcSrcFile)" y modificarlo sin grabar y que lea los cambios?
ResponderBorrarDesde ya muchas gracias