diff --git a/FoxBin2PRGVersionFile.txt b/FoxBin2PRGVersionFile.txt index fdcb68e..721a181 100644 --- a/FoxBin2PRGVersionFile.txt +++ b/FoxBin2PRGVersionFile.txt @@ -3,7 +3,7 @@ Lparameters toUpdateInfo Local lcNote With toUpdateInfo .VersionNumber = 'v1.19.47' - .VersionDate = Date(2016,05,24) + .VersionDate = Date(2016,05,28) .SourceFileUrl = 'http://vfpxrepository.com/dl/thorupdate/Projects/FoxBin2Prg/FoxBin2Prg.Zip' .Link = 'http://vfpx.codeplex.com/wikipage?title=FoxBin2PRG' @@ -17,13 +17,14 @@ Demo video using FoxBin2Prg with PlasticSCM: http://youtu.be/sE4wQ50Itqg Change History ------------------------------------------------------------- -2016/05/24 v1.19.47 +2016/05/28 v1.19.47 - Bug Fix: When a filename "*" is specified with a type "*", an automatic regeneration of all binary files is made from text files (Alejandro Sosa) - BugFix: Added variable declaration (Doug Hennig) - BugFix: Fixed incorrectly named variable (Doug Hennig) - BugFix: Added missing assignment (Doug Hennig) - Enhancement: Put double quotes around path in case in contains single quote (Doug Hennig) - BugFix: Added "+16" to Debug flags to maintain internal defaults to not generate timestamps on xx2 files +- Feature: Added support for appending data from DB2 to DBF with the new value DBF_Conversion_Support=8. All datatypes except General. (Walter Nicholls) 2016/02/06 v1.19.46 - Bug Fix: set_UserValue() method causes error when trying to get information about another error and the VFP binary table can not be opened (ie, because corrupted memo) diff --git a/TESTS/DATOS_READONLY/fb2p_free.cdx b/TESTS/DATOS_READONLY/fb2p_free.cdx index b5004ca..8857e9b 100644 Binary files a/TESTS/DATOS_READONLY/fb2p_free.cdx and b/TESTS/DATOS_READONLY/fb2p_free.cdx differ diff --git a/TESTS/DATOS_READONLY/FB2P_FREE.DB2 b/TESTS/DATOS_READONLY/fb2p_free.db2 similarity index 74% rename from TESTS/DATOS_READONLY/FB2P_FREE.DB2 rename to TESTS/DATOS_READONLY/fb2p_free.db2 index df554e5..3a8659c 100644 --- a/TESTS/DATOS_READONLY/FB2P_FREE.DB2 +++ b/TESTS/DATOS_READONLY/fb2p_free.db2 @@ -8,7 +8,7 @@ 1252 - 2013/12/12 + 0x00000032Visual FoxPro, Varchar, Varbinary, or Blob-enabled @@ -371,7 +371,7 @@ - 30 + 505 @@ -381,12 +381,12 @@ - LOGICO - BINARY - LOGICO - + CARACTER + CANDIDATE + CARACTER + .NOT.EMPTY(caracter) ASCENDING - MACHINE + GENERAL ENTERO @@ -397,13 +397,93 @@ MACHINE - CARACTER - CANDIDATE - CARACTER - .NOT.EMPTY(caracter) + LOGICO + BINARY + LOGICO + ASCENDING - GENERAL + MACHINE + + + + + / / + / / : : + .F. + 0.00000 + 0.000000 + 0.000 + + 0.0000 + 0 + + + + + ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg + + 45 + + + axaxaxaxaXAXA + 1969/11/26 + 1969/11/26 22:10:06 + .T. + 123.45676 + 123.456786 + 123.456 + NgAuAEUAcwB0AGEAIABlAHMAIAB1AG4AYQAgAGYAcgBhAHMAZQAgAGMAbwBkAGkAZgBpAGMAYQBkAGEAIABlAG4AIABoAGUAeABhACAAeQAgAGMAbwBuACAAYwBhAHIAYQBjAHQAZQByAGUAcwAgAGUAcwBwAGUAYwBpAGEAbABlAHMALgAgAOEA6QDtAPMA+gDBAMkAzQDTANoAxADLAM8A1gDcAOQA6wDvAPYA/ADgAOgA7ADyAPkA8QDRAMcA5wBeAA== + 12345.6786 + 1234567896 + 6.notas TXT. áéíóúÄËÏÖÜÑñäëïöü. ^FinÇç + Ni5GcmFzZSBVVEYtOC4gw6HDqcOtw7PDusOEw4vDj8OWw5w= + var char 6.áéíóúÜÑ + yQBzAHQAYQAgAGUAcwAgAGwAYQAgAHMAZQDxAGEAbAAhAA== + Q2hhckJpbi02LsOhw6nDrcOzw7rDnMORICAgICAg + VkNoYXJCaW4tNi7DocOpw63Ds8O6w5zDkQ== + 35 + + + lalal.áéíóúÜÑ + 1969/11/27 + 1969/11/27 22:10:07 + .T. + 123.45677 + 123.456787 + 123.457 + NwAuAEUAcwB0AGEAIABlAHMAIAB1AG4AYQAgAGYAcgBhAHMAZQAgAGMAbwBkAGkAZgBpAGMAYQBkAGEAIABlAG4AIABoAGUAeABhACAAeQAgAGMAbwBuACAAYwBhAHIAYQBjAHQAZQByAGUAcwAgAGUAcwBwAGUAYwBpAGEAbABlAHMALgAgAOEA6QDtAPMA+gDBAMkAzQDTANoAxADLAM8A1gDcAOQA6wDvAPYA/ADgAOgA7ADyAPkA8QDRAMcA5wBeAA== + 12345.6787 + 1234567897 + 7.notas TXT. áéíóúÄËÏÖÜÑñäëïöü. ^FinÇç + Ny5GcmFzZSBVVEYtOC4gw6HDqcOtw7PDusOEw4vDj8OWw5w= + var char 7.áéíóúÜÑ + yQB4AGkAdABvAHMAIADaAG4AaQBjAG8AcwAhACAAOgApAA== + Q2hhckJpbi03LsOhw6nDrcOzw7rDnMORICAgICAg + VkNoYXJCaW4tNy7DocOpw63Ds8O6w5zDkQ== + 30 + + + pepepepepEPE + 1969/11/25 + 1969/11/25 22:10:05 + .T. + 123.45675 + 123.456785 + 123.455 + NQAuAEUAcwB0AGEAIABlAHMAIAB1AG4AYQAgAGYAcgBhAHMAZQAgAGMAbwBkAGkAZgBpAGMAYQBkAGEAIABlAG4AIABoAGUAeABhACAAeQAgAGMAbwBuACAAYwBhAHIAYQBjAHQAZQByAGUAcwAgAGUAcwBwAGUAYwBpAGEAbABlAHMALgAgAOEA6QDtAPMA+gDBAMkAzQDTANoAxADLAM8A1gDcAOQA6wDvAPYA/ADgAOgA7ADyAPkA8QDRAMcA5wBeAA== + 12345.6785 + 1234567895 + 5.notas TXT. áéíóúÄËÏÖÜÑñäëïöü. ^FinÇç + NS5GcmFzZSBVVEYtOC4gw6HDqcOtw7PDusOEw4vDj8OWw5w= + var char 5.áéíóúÜÑ + yQBzAHQAYQAgAGUAcwAgAGwAYQAgAHMAZQDxAGEAbAAhAA== + Q2hhckJpbi01LsOhw6nDrcOzw7rDnMORICAgICAg + VkNoYXJCaW4tNS7DocOpw63Ds8O6w5zDkQ== + 40 + + +
diff --git a/TESTS/DATOS_READONLY/fb2p_free.dbf b/TESTS/DATOS_READONLY/fb2p_free.dbf index 72cf766..e166f21 100644 Binary files a/TESTS/DATOS_READONLY/fb2p_free.dbf and b/TESTS/DATOS_READONLY/fb2p_free.dbf differ diff --git a/TESTS/DATOS_READONLY/fb2p_free.dbf.cfg b/TESTS/DATOS_READONLY/fb2p_free.dbf.cfg new file mode 100644 index 0000000..2b5580f --- /dev/null +++ b/TESTS/DATOS_READONLY/fb2p_free.dbf.cfg @@ -0,0 +1,3 @@ +DBF_Conversion_Support: 8 +DBF_Conversion_Order: caracter +DBF_Conversion_Condition: .T. \ No newline at end of file diff --git a/TESTS/DATOS_READONLY/fb2p_free.fpt b/TESTS/DATOS_READONLY/fb2p_free.fpt index 601fa8d..06c9492 100644 Binary files a/TESTS/DATOS_READONLY/fb2p_free.fpt and b/TESTS/DATOS_READONLY/fb2p_free.fpt differ diff --git a/TESTS/ft__foxbin2prg__c_conversor_prg_a_dbf.prg b/TESTS/ft__foxbin2prg__c_conversor_prg_a_dbf.prg index 061c156..f17280c 100644 --- a/TESTS/ft__foxbin2prg__c_conversor_prg_a_dbf.prg +++ b/TESTS/ft__foxbin2prg__c_conversor_prg_a_dbf.prg @@ -286,9 +286,16 @@ DEFINE CLASS ft__foxbin2prg__c_conversor_prg_a_dbf AS FxuTestCase OF FxuTestCase this.assertequals( lnFields_OUT, lnFields_IN, '[Cantidad de campos IN y OUT]' ) FOR I = 1 TO lnFields_IN - FOR X = 1 TO 18 - THIS.assertequals( laCampos_IN(I,X), laCampos_OUT(I,X), '[Comparando estructura del campo ' + laCampos_IN(I,1) + ']' ) - ENDFOR + IF laCampos_IN(I,18) > 0 && Autoinc_Step + *-- Para los campos AutoInc solo se comparan los primeros 4 datos de estructura + FOR X = 1 TO 4 + THIS.assertequals( laCampos_IN(I,X), laCampos_OUT(I,X), '[Comparando estructura del campo ' + laCampos_IN(I,1) + ']' ) + ENDFOR + ELSE + FOR X = 1 TO 18 + THIS.assertequals( laCampos_IN(I,X), laCampos_OUT(I,X), '[Comparando estructura del campo ' + laCampos_IN(I,1) + ']' ) + ENDFOR + ENDIF ENDFOR CATCH TO loEx diff --git a/foxbin2prg.cfg.txt b/foxbin2prg.cfg.txt index da907ad..338f943 100644 --- a/foxbin2prg.cfg.txt +++ b/foxbin2prg.cfg.txt @@ -1,5 +1,5 @@ **************************************************************************************************** -* FOXBIN2PRG v1.19.43 +* FOXBIN2PRG v1.19.47 * CONFIGURATION FILE / ARCHIVO DE CONFIGURACIÓN **************************************************************************************************** @@ -34,7 +34,7 @@ * LBX_Conversion_Support: 2 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge) * MNX_Conversion_Support: 2 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge) * DBC_Conversion_Support: 2 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge) -* DBF_Conversion_Support: 1 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge), 4=Generate TXT with DATA for DIFF (No Bidirectional!) +* DBF_Conversion_Support: 1 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge/Only Structure!), 4=Generate TXT with DATA (Diff), 8=Export and Import DATA (Merge/Structure & Data) * >>DBF_Conversion_Support NOTE: >> EN: FoxBin2Prg support bi-directional convertion of DBFs, but does not keep data. Use with care. * >> ES: FoxBin2Prg tiene soporte bi-direccional para convertir DBF, pero no mantiene los datos. Usar con cuidado. * DBF_Conversion_Included: * && If DBF_Conversion_Support:4, you can specify multiple filemasks: www,fb2p_free.dbf / Si DBF_Conversion_Support:4, se pueden indicar múltiples máscaras de archivo: www,fb2p_free.dbf diff --git a/foxbin2prg.exe b/foxbin2prg.exe index c46a8c7..4f1db04 100644 Binary files a/foxbin2prg.exe and b/foxbin2prg.exe differ diff --git a/foxbin2prg.prg b/foxbin2prg.prg index 66ac7d6..08d52eb 100644 --- a/foxbin2prg.prg +++ b/foxbin2prg.prg @@ -182,7 +182,8 @@ * 25/11/2015 FDBOZZO v1.19.46 Bug Fix Pj2: Se genera un error al regenerar un PJX desde un PJ2 donde algún archivo contiene paréntesis (EddieC) * 25/11/2015 FDBOZZO v1.19.46 Mejora dbf: Nuevo parámetro ExcludeDBFAutoincNextval para evitar diferencias por este dato (edyshor) * 04/02/2016 FDBOZZO v1.19.46 Bug Fix: Cuando se procesa un archivo en el directorio raiz, se genera un error 2062 (Aurélien Dellieux) -* 10/02/2016 FDBOZZO v1.19.46 Bug Fix: Cuando se indica como nombre de archivo "*" y como tipo "*", se regeneran automáticamente todos los archivos binarios desde los archivos de texto (Alejandro Sosa) +* 10/02/2016 FDBOZZO v1.19.47 Bug Fix: Cuando se indica como nombre de archivo "*" y como tipo "*", se regeneran automáticamente todos los archivos binarios desde los archivos de texto (Alejandro Sosa) +* 25/05/2016 FDBOZZO v1.19.47 Mejora DBF-Data: Permitir importar datos de los DB2 a los DBF con el nuevo valor DBF_Conversion_Support=8. Todos los tipos de datos excepto General. (Walter Nicholls) * * *--------------------------------------------------------------------------------------------------- @@ -461,7 +462,7 @@ LPARAMETERS tc_InputFile, tcType, tcTextName, tlGenText, tcDontShowErrors, tcDeb *** DH 06/02/2014: added additional constants #DEFINE C_RECORDS_I '' #DEFINE C_RECORDS_F '' -#DEFINE C_RECORD_I '' && *** FDBOZZO 2014/07/15: Optimized RECORD tag adding num property to not use REGNUM field +#DEFINE C_RECORD_I '' && *** FDBOZZO 2016/06/06: Quitado el REGNUM para evitar diferencias innecesarias #DEFINE C_RECORD_F '' #DEFINE C_RECNO_I '' #DEFINE C_RECNO_F '' @@ -798,7 +799,8 @@ DEFINE CLASS c_foxbin2prg AS Session o_Conversor = NULL o_Frm_Avance = NULL o_WSH = NULL - o_FSO = NULL + o_FSO = NULL && Scripting.FileSystemObject + o_TextStream = NULL && Scripting.TextStream o_FNC = NULL && Filename_caps object o_Configuration = NULL run_AfterCreateTable = '' @@ -2119,7 +2121,7 @@ DEFINE CLASS c_foxbin2prg AS Session CASE LEFT( laConfig(I), 23 ) == LOWER('DBF_Conversion_Support:') lcValue = ALLTRIM( SUBSTR( laConfig(I), 24 ) ) - IF INLIST( lcValue, '0', '1', '2', '4' ) THEN + IF INLIST( lcValue, '0', '1', '2', '4', '8' ) THEN lo_CFG.DBF_Conversion_Support = INT( VAL( lcValue ) ) .writeLog( C_TAB + JUSTFNAME(lcConfigFile) + ' > DBF_Conversion_Support: ' + TRANSFORM(lo_CFG.DBF_Conversion_Support) ) ENDIF @@ -2354,6 +2356,67 @@ DEFINE CLASS c_foxbin2prg AS Session ENDFUNC + PROCEDURE get_DBF_Configuration(tc_InputFile as String, to_out_DBF_CFG as Object, tlGenerateLog as Boolean) as Integer + *--------------------------------------------------------------------------------------------------- + * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) + * tc_InputFile (@! IN ) Ruta al archivo con Extensión para comprobar si tiene soporte de conversión + * to_out_DBF_CFG (@? OUT) Objeto CFG del DBF indicado, con las propiedades que contenga el CFG y sus valores + * RETORNO (v? OUT) Devuelve 0 si no existe el archivo CFG y 1 si lo encuentra + *--------------------------------------------------------------------------------------------------- + #IF .F. + LOCAL to_out_DBF_CFG AS CL_DBF_CFG OF 'FOXBIN2PRG.PRG' + #ENDIF + + LOCAL lcTableCFG, lnFileCount, laDirFile(1,5), I, lcConfigItem + lcTableCFG = tc_InputFile + '.CFG' + lnFileCount = ADIR(laDirFile, lcTableCFG) + + IF lnFileCount = 1 + to_out_DBF_CFG = CREATEOBJECT("CL_DBF_CFG") + + IF tlGenerateLog THEN + THIS.writeLog() + THIS.writeLog(' > Found DBF configuration file: ' + lcTableCFG) + ENDIF + + FOR I = 1 TO ALINES( laConfig, FILETOSTR( lcTableCFG ), 1+4 ) + lcConfigItem = LOWER( laConfig(I) ) + + DO CASE + CASE INLIST( LEFT( lcConfigItem, 1 ), '*', '#', '/', "'" ) + LOOP + + CASE LEFT( lcConfigItem, 21 ) == LOWER('DBF_Conversion_Order:') + to_out_DBF_CFG.DBF_Conversion_Order = ALLTRIM( SUBSTR( laConfig(I), 22 ) ) + IF tlGenerateLog THEN + THIS.writeLog(' ' + JUSTFNAME(lcTableCFG) + ' > DBF_Conversion_Order: ' + to_out_DBF_CFG.DBF_Conversion_Order ) + ENDIF + + CASE LEFT( lcConfigItem, 25 ) == LOWER('DBF_Conversion_Condition:') + to_out_DBF_CFG.DBF_Conversion_Condition = ALLTRIM( SUBSTR( laConfig(I), 26 ) ) + IF tlGenerateLog THEN + THIS.writeLog(' ' + JUSTFNAME(lcTableCFG) + ' > DBF_Conversion_Condition: ' + to_out_DBF_CFG.DBF_Conversion_Condition ) + ENDIF + + CASE LEFT( lcConfigItem, 23 ) == LOWER('DBF_Conversion_Support:') + to_out_DBF_CFG.DBF_Conversion_Support = INT( VAL( SUBSTR( laConfig(I), 24 ) ) ) + IF tlGenerateLog THEN + THIS.writeLog(' ' + JUSTFNAME(lcTableCFG) + ' > DBF_Conversion_Support: ' + TRANSFORM(to_out_DBF_CFG.DBF_Conversion_Support) ) + ENDIF + + ENDCASE + ENDFOR + + IF tlGenerateLog THEN + THIS.writeLog() + ENDIF + + ENDIF + + RETURN lnFileCount + ENDPROC + + PROCEDURE get_Ext2FromExt *--------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) @@ -2387,72 +2450,135 @@ DEFINE CLASS c_foxbin2prg AS Session ENDPROC - PROCEDURE hasSupport_Bin2Prg + PROCEDURE hasSupport_Bin2Prg(tcFileName as String, tcDir as String) as Boolean *--------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) - * tcExt (@! IN ) Extensión para comprobar si tiene soporte de conversión + * tcFilename (@! IN ) Extensión para comprobar si el archivo tiene soporte de conversión * tcDir (@? IN ) Directorio del que devolver su configuración * RETORNO (v? OUT) .T. si tiene soporte de conversión, .F. si no lo tiene *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcExt, tcDir - - LOCAL llhasSupport - tcExt = UPPER(JUSTEXT('.' + tcExt)) + LOCAL llhasSupport, lcExt, lcDir ; + , loDBF_CFG AS CL_DBF_CFG OF 'FOXBIN2PRG.PRG' WITH THIS AS c_foxbin2prg OF 'FOXBIN2PRG.PRG' - IF NOT EMPTY(tcDir) - .evaluateConfiguration( '', '', '', '', '', '', '', '', tcDir, 'D' ) + loDBF_CFG = NULL + lcExt = UPPER(JUSTEXT('.' + tcFileName)) + + IF '\' $ tcFileName AND lcExt == 'DBF' THEN + lcDir = JUSTPATH(tcFileName) + .get_DBF_Configuration(tcFileName, @loDBF_CFG) + ELSE + lcDir = tcDir ENDIF - llhasSupport = ICASE( tcExt == 'PJX', .PJX_Conversion_Support > 0 ; - , tcExt == 'VCX', .VCX_Conversion_Support > 0 ; - , tcExt == 'SCX', .SCX_Conversion_Support > 0 ; - , tcExt == 'FRX', .FRX_Conversion_Support > 0 ; - , tcExt == 'LBX', .LBX_Conversion_Support > 0 ; - , tcExt == 'MNX', .MNX_Conversion_Support > 0 ; - , tcExt == 'DBF', .DBF_Conversion_Support > 0 ; - , tcExt == 'DBC', .DBC_Conversion_Support > 0 ; + IF NOT EMPTY(lcDir) + .evaluateConfiguration( '', '', '', '', '', '', '', '', lcDir, 'D' ) + ENDIF + + llhasSupport = ICASE( lcExt == 'PJX', .PJX_Conversion_Support > 0 ; + , lcExt == 'VCX', .VCX_Conversion_Support > 0 ; + , lcExt == 'SCX', .SCX_Conversion_Support > 0 ; + , lcExt == 'FRX', .FRX_Conversion_Support > 0 ; + , lcExt == 'LBX', .LBX_Conversion_Support > 0 ; + , lcExt == 'MNX', .MNX_Conversion_Support > 0 ; + , lcExt == 'DBF', .DBF_Conversion_Support > 0 OR NOT ISNULL(loDBF_CFG) ; + , lcExt == 'DBC', .DBC_Conversion_Support > 0 ; , .F. ) ENDWITH && THIS - RELEASE tcExt RETURN llhasSupport ENDPROC - PROCEDURE hasSupport_Prg2Bin + PROCEDURE hasSupport_Prg2Bin(tcFileName as String, tcDir as String) as Boolean *--------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) - * tcExt (@! IN ) Extensión para comprobar si tiene soporte de conversión + * tcFilename (@! IN ) Extensión para comprobar si el archivo tiene soporte de conversión * tcDir (@? IN ) Directorio del que devolver su configuración * RETORNO (v? OUT) .T. si tiene soporte de conversión, .F. si no lo tiene *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcExt, tcDir - - LOCAL llhasSupport - tcExt = UPPER(JUSTEXT('.' + tcExt)) + LOCAL llhasSupport, lcExt, lcDir ; + , loDBF_CFG AS CL_DBF_CFG OF 'FOXBIN2PRG.PRG' WITH THIS AS c_foxbin2prg OF 'FOXBIN2PRG.PRG' - IF NOT EMPTY(tcDir) - .evaluateConfiguration( '', '', '', '', '', '', '', '', tcDir, 'D' ) + loDBF_CFG = NULL + lcExt = UPPER(JUSTEXT('.' + tcFileName)) + + IF '\' $ tcFileName AND lcExt == .c_DB2 THEN + lcDir = JUSTPATH(tcFileName) + .get_DBF_Configuration(tcFileName, @loDBF_CFG) + ELSE + lcDir = tcDir ENDIF - llhasSupport = ICASE( tcExt == .c_PJ2, .PJX_Conversion_Support = 2 ; - , tcExt == .c_VC2, .VCX_Conversion_Support = 2 ; - , tcExt == .c_SC2, .SCX_Conversion_Support = 2 ; - , tcExt == .c_FR2, .FRX_Conversion_Support = 2 ; - , tcExt == .c_LB2, .LBX_Conversion_Support = 2 ; - , tcExt == .c_MN2, .MNX_Conversion_Support = 2 ; - , tcExt == .c_DB2, .DBF_Conversion_Support = 2 ; - , tcExt == .c_DC2, .DBC_Conversion_Support = 2 ; + IF NOT EMPTY(lcDir) + .evaluateConfiguration( '', '', '', '', '', '', '', '', lcDir, 'D' ) + ENDIF + + llhasSupport = ICASE( lcExt == .c_PJ2, .PJX_Conversion_Support = 2 ; + , lcExt == .c_VC2, .VCX_Conversion_Support = 2 ; + , lcExt == .c_SC2, .SCX_Conversion_Support = 2 ; + , lcExt == .c_FR2, .FRX_Conversion_Support = 2 ; + , lcExt == .c_LB2, .LBX_Conversion_Support = 2 ; + , lcExt == .c_MN2, .MNX_Conversion_Support = 2 ; + , lcExt == .c_DB2, INLIST(.DBF_Conversion_Support, 2, 8) OR NOT ISNULL(loDBF_CFG) AND loDBF_CFG.DBF_Conversion_Support = 8 ; + , lcExt == .c_DC2, .DBC_Conversion_Support = 2 ; , .F. ) ENDWITH && THIS - RELEASE tcExt RETURN llhasSupport ENDPROC + PROCEDURE conversionSupportType(tcFileName as String, tlGenerarLog as Boolean) as Integer + *--------------------------------------------------------------------------------------------------- + * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) + * tcFilename (@! IN ) Extensión para comprobar si el archivo tiene soporte de conversión + * RETORNO (v? OUT) Devuelve el código de soporte + *--------------------------------------------------------------------------------------------------- + LOCAL lnSupportType, lcExt, lcDir, lcFilename ; + , loDBF_CFG AS CL_DBF_CFG OF 'FOXBIN2PRG.PRG' + + TRY + WITH THIS AS c_foxbin2prg OF 'FOXBIN2PRG.PRG' + loDBF_CFG = NULL + lcExt = UPPER(JUSTEXT('.' + tcFileName)) + + IF '\' $ tcFileName AND INLIST(lcExt, .c_DB2, 'DBF') THEN + lcFilename = FORCEEXT(tcFileName, 'DBF') + lcDir = JUSTPATH(lcFilename) + .get_DBF_Configuration(lcFilename, @loDBF_CFG, tlGenerarLog) + ELSE + lcDir = SYS(5) + CURDIR() + ENDIF + + IF NOT EMPTY(lcDir) + .evaluateConfiguration( '', '', '', '', '', '', '', '', lcDir, 'D' ) + ENDIF + + lnSupportType = ICASE( ; + INLIST(lcExt, .c_PJ2, 'PJX'), .PJX_Conversion_Support ; + , INLIST(lcExt, .c_VC2, 'VCX'), .VCX_Conversion_Support ; + , INLIST(lcExt, .c_SC2, 'SCX'), .SCX_Conversion_Support ; + , INLIST(lcExt, .c_FR2, 'FRX'), .FRX_Conversion_Support ; + , INLIST(lcExt, .c_LB2, 'LBX'), .LBX_Conversion_Support ; + , INLIST(lcExt, .c_MN2, 'MNX'), .MNX_Conversion_Support ; + , INLIST(lcExt, .c_DB2, 'DBF'), ICASE( ISNULL(loDBF_CFG) OR loDBF_CFG.DBF_Conversion_Support = 0, .DBF_Conversion_Support, loDBF_CFG.DBF_Conversion_Support ) ; + , INLIST(lcExt, .c_DC2, 'DBC'), .DBC_Conversion_Support ; + , 0 ) + + lnSupportType = INT(lnSupportType) + ENDWITH && THIS + + FINALLY + STORE NULL TO loDBF_CFG + RELEASE loDBF_CFG + ENDTRY + + RETURN lnSupportType + ENDPROC + + PROCEDURE execute *-------------------------------------------------------------------------------------------------------------- * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT) @@ -3552,7 +3678,7 @@ DEFINE CLASS c_foxbin2prg AS Session .changeFileAttribute( FORCEEXT( .c_InputFile, .c_LB2 ), lcForceAttribs ) CASE lcExtension = 'DBF' - IF NOT INLIST(.DBF_Conversion_Support, 1, 2, 4) + IF NOT INLIST(.DBF_Conversion_Support, 1, 2, 4, 8) ERROR (TEXTMERGE(loLang.C_FILE_NAME_IS_NOT_SUPPORTED_LOC)) ENDIF .c_OutputFile = FORCEEXT( .c_InputFile, .c_DB2 ) @@ -3621,7 +3747,9 @@ DEFINE CLASS c_foxbin2prg AS Session .changeFileAttribute( FORCEEXT( .c_InputFile, 'LBT' ), lcForceAttribs ) CASE lcExtension = .c_DB2 - IF .DBF_Conversion_Support <> 2 + IF INLIST(.DBF_Conversion_Support, 2, 8) OR ADIR(laDirFile, FORCEEXT(.c_InputFile, 'DBF') + '.CFG') = 1 THEN + *-- Soporte txt-2-bin habilitado + ELSE ERROR (TEXTMERGE(loLang.C_FILE_NAME_IS_NOT_SUPPORTED_LOC)) ENDIF .c_OutputFile = FORCEEXT( .c_InputFile, 'DBF' ) @@ -11886,6 +12014,8 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin + [] ; + [] ; + [] ; + + [] ; + + [] ; + [] c_Type = 'DB2' @@ -11907,7 +12037,9 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin TRY LOCAL lnCodError, loEx AS EXCEPTION, laCodeLines(1), lnCodeLines, laLineasExclusion(1), lnBloquesExclusion, I ; - , lnIDInputFile + , lnIDInputFile, lnFileCount, laConfig(1), lcConfigItem, lc_DBF_Conversion_Support, lcAlterTable ; + , lcTempDBC, llImportData ; + , loDBF_CFG AS CL_DBF_CFG OF 'FOXBIN2PRG.PRG' STORE 0 TO lnCodError, lnCodeLines WITH THIS AS c_conversor_prg_a_dbf OF 'FOXBIN2PRG.PRG' @@ -11922,12 +12054,23 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin EXIT && Si se indicó no procesar, se sale aquí. (Modo de simulación) ENDIF + *-- If table CFG exists, use it for DBF-specific configuration. FDBOZZO. 2014/06/15 + lnFileCount = toFoxBin2Prg.get_DBF_Configuration( FORCEEXT(.c_InputFile, 'DBF'), @loDBF_CFG, .T. ) + lcTempDBC = FORCEPATH( '_FB2P', JUSTPATH(.c_OutputFile) ) + + DO CASE + CASE toFoxBin2Prg.DBF_Conversion_Support = 8 && TXT2BIN (DATA IMPORT) + llImportData = .T. + CASE INLIST(toFoxBin2Prg.DBF_Conversion_Support, 1, 2, 4) AND lnFileCount = 1 + llImportData = (loDBF_CFG.DBF_Conversion_Support = 8) + ENDCASE + C_FB2PRG_CODE = FILETOSTR( .c_InputFile ) lnCodeLines = ALINES( laCodeLines, C_FB2PRG_CODE ) toFoxBin2Prg.doBackup( .F., .T., '', '', '' ) - *-- Identifico el inicio/fin de bloque, definición, cabecera y cuerpo del reporte + *-- Identifico el inicio/fin de bloque, campos e índices de la tabla .identifyCodeBlocks( @laCodeLines, lnCodeLines, @laLineasExclusion, lnBloquesExclusion, @toTable ) DO CASE @@ -11943,7 +12086,20 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin ENDIF toFoxBin2Prg.updateProcessedFile( lnIDInputFile ) - .writeBinaryFile( @toTable, @toFoxBin2Prg ) + .writeBinaryFile_STRUCTURE( @toTable, @toFoxBin2Prg, @lcAlterTable ) + + IF llImportData AND lnCodeLines > 1 AND toTable._I > 1 THEN + *-- Identifico los registros de la tabla y los agrego + I = toTable._I - 1 + toTable.analyzeCodeBlock( C_TABLE_I, @laCodeLines, @I, lnCodeLines, @toFoxBin2Prg ) + ENDIF + + IF NOT EMPTY(lcAlterTable) + EXECSCRIPT(lcAlterTable) + ENDIF + + .writeBinaryFile_INDEXES( @toTable, @toFoxBin2Prg ) + ENDWITH && THIS @@ -11958,6 +12114,18 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin FINALLY USE IN (SELECT("TABLABIN")) + USE IN (SELECT(JUSTSTEM(THIS.c_OutputFile))) + + IF NOT EMPTY(lcTempDBC) + CLOSE DATABASES + ERASE (FORCEEXT(lcTempDBC,'DBC')) + ERASE (FORCEEXT(lcTempDBC,'DCT')) + ERASE (FORCEEXT(lcTempDBC,'DCX')) + ENDIF + + STORE NULL TO loDBF_CFG + RELEASE loDBF_CFG + ENDTRY RETURN lnCodError @@ -11965,8 +12133,8 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin - PROCEDURE writeBinaryFile - LPARAMETERS toTable, toFoxBin2Prg + PROCEDURE writeBinaryFile_STRUCTURE + LPARAMETERS toTable, toFoxBin2Prg, tcAlterTable *-- ----------------------------------------------------------------------------------------------------------- #IF .F. LOCAL toTable AS CL_DBF_TABLE OF 'FOXBIN2PRG.PRG' @@ -11976,16 +12144,15 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin TRY LOCAL I, lnCodError, loEx AS EXCEPTION ; , loField AS CL_DBF_FIELD OF 'FOXBIN2PRG.PRG' ; - , loIndex AS CL_DBF_INDEX OF 'FOXBIN2PRG.PRG' ; , loDBFUtils AS CL_DBF_UTILS OF 'FOXBIN2PRG.PRG' ; - , lcCreateTable, lcLongDec, lcFieldDef, lcIndex, ldLastUpdate, lcTempDBC, lnDataSessionID, lnSelect + , lcCreateTable, lcLongDec, lcFieldDef, lcIndex, lcTempDBC, lnDataSessionID, lnSelect WITH THIS AS c_conversor_prg_a_dbf OF 'FOXBIN2PRG.PRG' STORE NULL TO loField, loIndex, loDBFUtils loDBFUtils = CREATEOBJECT('CL_DBF_UTILS') STORE 0 TO lnCodError - STORE '' TO lcIndex, lcFieldDef + STORE '' TO lcIndex, lcFieldDef, tcAlterTable lnDataSessionID = toFoxBin2Prg.DATASESSIONID *-- addProcessedFile( tcFile, tcInOutType, tcProcessed, tcHasErrors, tcSupported, tcExpanded ) @@ -12001,19 +12168,25 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin ERASE (FORCEEXT(.c_OutputFile, 'CDX')) IF EMPTY(toTable._Database) - lcCreateTable = 'CREATE TABLE "' + .c_OutputFile + '" FREE CodePage=' + toTable._CodePage + ' (' + lcCreateTable = 'CREATE TABLE "' + .c_OutputFile + '" FREE CodePage=' + toTable._CodePage + ' ;' + CR_LF + ' (' ELSE lcTempDBC = FORCEPATH( '_FB2P', JUSTPATH(.c_OutputFile) ) CREATE DATABASE ( lcTempDBC ) - lcCreateTable = 'CREATE TABLE "' + .c_OutputFile + '" CodePage=' + toTable._CodePage + ' (' + lcCreateTable = 'CREATE TABLE "' + .c_OutputFile + '" CodePage=' + toTable._CodePage + ' ;' + CR_LF + ' (' ENDIF + toTable._TableName = .c_OutputFile + *-- Conformo los campos FOR EACH loField IN toTable._Fields FOXOBJECT lcLongDec = '' + IF NOT EMPTY(lcFieldDef) + lcFieldDef = lcFieldDef + ';' + CR_LF + ', ' + ENDIF + *-- Nombre, Tipo - lcFieldDef = lcFieldDef + ', ' + loField._Name + ' ' + loField._Type + lcFieldDef = lcFieldDef + loField._Name + ' ' + loField._Type *-- Longitud IF INLIST( loField._Type, 'C', 'N', 'F', 'Q', 'V' ) @@ -12051,15 +12224,19 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin *-- of DBF with this field. lcFieldDef = lcFieldDef + ' AUTOINC NEXTVAL 1 STEP ' + loField._AutoInc_Step ELSE - lcFieldDef = lcFieldDef + ' AUTOINC NEXTVAL ' + loField._AutoInc_NextVal + ' STEP ' + loField._AutoInc_Step + tcAlterTable = tcAlterTable + ' ;' + CR_LF + ' ALTER ' + loField._Name + ' ' + loField._Type + ' AUTOINC NEXTVAL ' + loField._AutoInc_NextVal + ' STEP ' + loField._AutoInc_Step ENDIF ENDIF loField = NULL ENDFOR - lcCreateTable = lcCreateTable + SUBSTR(lcFieldDef,3) + ')' - &lcCreateTable. + lcCreateTable = lcCreateTable + lcFieldDef + ')' + EXECSCRIPT(lcCreateTable) + + IF NOT EMPTY(tcAlterTable) + tcAlterTable = 'ALTER TABLE "' + .c_OutputFile + '" ' + tcAlterTable + ENDIF *-- Hook para permitir ejecución externa (por ejemplo, para rellenar la tabla con datos) IF NOT EMPTY(toFoxBin2Prg.run_AfterCreateTable) @@ -12069,6 +12246,53 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin SELECT (lnSelect) ENDIF + ENDWITH && THIS + + + CATCH TO loEx + lnCodError = loEx.ERRORNO + toFoxBin2Prg.updateProcessedFile( 0, '', '', 'E1' ) + loEx.USERVALUE = 'lcFieldDef="' + TRANSFORM(lcFieldDef) + '"' + CR_LF ; + + 'lcCreateTable="' + TRANSFORM(lcCreateTable) + '"' + + IF THIS.n_Debug > 0 AND _VFP.STARTMODE = 0 + SET STEP ON + ENDIF + + THROW + + FINALLY + STORE NULL TO loField, loDBFUtils + RELEASE I, loField, loDBFUtils ; + , lcCreateTable, lcLongDec, lcFieldDef, lcTempDBC, lnDataSessionID, lnSelect + + ENDTRY + + RETURN lnCodError + ENDPROC + + + + PROCEDURE writeBinaryFile_INDEXES + LPARAMETERS toTable, toFoxBin2Prg + *-- ----------------------------------------------------------------------------------------------------------- + #IF .F. + LOCAL toTable AS CL_DBF_TABLE OF 'FOXBIN2PRG.PRG' + LOCAL toFoxBin2Prg AS c_foxbin2prg OF 'FOXBIN2PRG.PRG' + #ENDIF + + TRY + LOCAL I, lnCodError, loEx AS EXCEPTION ; + , loIndex AS CL_DBF_INDEX OF 'FOXBIN2PRG.PRG' ; + , loDBFUtils AS CL_DBF_UTILS OF 'FOXBIN2PRG.PRG' ; + , ldLastUpdate + + WITH THIS AS c_conversor_prg_a_dbf OF 'FOXBIN2PRG.PRG' + STORE NULL TO loIndex + STORE 0 TO lnCodError + STORE '' TO lcIndex + loDBFUtils = CREATEOBJECT('CL_DBF_UTILS') + *-- Regenero los índices FOR EACH loIndex IN toTable._Indexes FOXOBJECT lcIndex = 'INDEX ON ' + loIndex._Key + ' TAG ' + loIndex._TagName @@ -12112,9 +12336,7 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin CATCH TO loEx lnCodError = loEx.ERRORNO toFoxBin2Prg.updateProcessedFile( 0, '', '', 'E1' ) - loEx.USERVALUE = 'lcIndex="' + TRANSFORM(lcIndex) + '"' + CR_LF ; - + 'lcFieldDef="' + TRANSFORM(lcFieldDef) + '"' + CR_LF ; - + 'lcCreateTable="' + TRANSFORM(lcCreateTable) + '"' + loEx.USERVALUE = 'lcIndex="' + TRANSFORM(lcIndex) + '"' IF THIS.n_Debug > 0 AND _VFP.STARTMODE = 0 SET STEP ON @@ -12123,18 +12345,8 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin THROW FINALLY - USE IN (SELECT(JUSTSTEM(THIS.c_OutputFile))) - STORE NULL TO loField, loIndex, loDBFUtils - - IF NOT EMPTY(lcTempDBC) - CLOSE DATABASES - ERASE (FORCEEXT(lcTempDBC,'DBC')) - ERASE (FORCEEXT(lcTempDBC,'DCT')) - ERASE (FORCEEXT(lcTempDBC,'DCX')) - ENDIF - - RELEASE I, loField, loIndex, loDBFUtils ; - , lcCreateTable, lcLongDec, lcFieldDef, lcIndex, ldLastUpdate, lcTempDBC, lnDataSessionID, lnSelect + STORE NULL TO loIndex + RELEASE I, loIndex, lcIndex, ldLastUpdate ENDTRY @@ -12183,6 +12395,7 @@ DEFINE CLASS c_conversor_prg_a_dbf AS c_conversor_prg_a_bin CASE NOT llBloqueTable_Completed AND toTable.analyzeCodeBlock( @lcLine, @taCodeLines, @I, tnCodeLines ) llBloqueTable_Completed = .T. + EXIT ENDCASE ENDFOR @@ -16563,9 +16776,12 @@ DEFINE CLASS c_conversor_dbf_a_prg AS c_conversor_bin_a_prg , ln_HexFileType, ll_FileHasCDX, ll_FileHasMemo, ll_FileIsDBC, lc_DBC_Name, lnDataSessionID, lnSelect, laDirInfo(1,5) ; , loTable AS CL_DBF_TABLE OF 'FOXBIN2PRG.PRG' ; , loDBFUtils AS CL_DBF_UTILS OF 'FOXBIN2PRG.PRG' ; - , loLang as CL_LANG OF 'FOXBIN2PRG.PRG' + , loLang as CL_LANG OF 'FOXBIN2PRG.PRG' ; + , loFSO AS Scripting.FileSystemObject ; + , loTextStream AS Scripting.TextStream loLang = _SCREEN.o_FoxBin2Prg_Lang + loFSO = toFoxBin2Prg.o_FSO STORE NULL TO loTable, loDBFUtils STORE 0 TO lnCodError loDBFUtils = CREATEOBJECT('CL_DBF_UTILS') @@ -16601,15 +16817,19 @@ DEFINE CLASS c_conversor_dbf_a_prg AS c_conversor_bin_a_prg *-- Exportación de estructura y datos (para Diff solamente) ERASE (.c_OutputFile + '.TMP' ) - toFoxBin2Prg.n_FileHandle = FCREATE( .c_OutputFile + '.TMP' ) + *toFoxBin2Prg.n_FileHandle = FCREATE( .c_OutputFile + '.TMP' ) + loTextStream = loFSO.CreateTextFile(.c_OutputFile + '.TMP' ) && Replace VFP low-level file funcs.because the 8-16KB limit. + toFoxBin2Prg.o_TextStream = loTextStream IF toFoxBin2Prg.n_FileHandle = -1 THEN ERROR 102, (.c_OutputFile) ENDIF - FWRITE( toFoxBin2Prg.n_FileHandle, C_FB2PRG_CODE ) + *FWRITE( toFoxBin2Prg.n_FileHandle, C_FB2PRG_CODE ) + loTextStream.WriteLine( C_FB2PRG_CODE ) && Replace VFP low-level file funcs.because the 8-16KB limit. loTable.toText( ln_HexFileType, ll_FileHasCDX, ll_FileHasMemo, ll_FileIsDBC, lc_DBC_Name, .c_InputFile, lc_FileTypeDesc, @toFoxBin2Prg ) - FCLOSE( toFoxBin2Prg.n_FileHandle ) + *FCLOSE( toFoxBin2Prg.n_FileHandle ) + loTextStream.Close() DO CASE CASE toFoxBin2Prg.c_SimulateError = 'SIMERR_I1' @@ -16681,7 +16901,10 @@ DEFINE CLASS c_conversor_dbf_a_prg AS c_conversor_bin_a_prg FINALLY USE IN (SELECT("TABLABIN")) - FCLOSE( toFoxBin2Prg.n_FileHandle ) + *FCLOSE( toFoxBin2Prg.n_FileHandle ) + IF VARTYPE(loTextStream) = "O" THEN + loTextStream.Close() + ENDIF *-- Cierro DBC FOR I = 1 TO ADATABASES(laDatabases2) @@ -16692,8 +16915,8 @@ DEFINE CLASS c_conversor_dbf_a_prg AS c_conversor_bin_a_prg ENDIF ENDFOR - STORE NULL TO loTable, loDBFUtils - RELEASE toModulo, toEx, toFoxBin2Prg ; + STORE NULL TO loTable, loDBFUtils, loTextStream, toFoxBin2Prg.o_TextStream + RELEASE toModulo, toEx, toFoxBin2Prg, loTextStream ; , lnCodError, laDatabases, lnDatabases_Count, laDatabases2, lnLen, lc_FileTypeDesc ; , ln_HexFileType, ll_FileHasCDX, ll_FileHasMemo, ll_FileIsDBC, lc_DBC_Name, lnDataSessionID, lnSelect ; , loTable, loDBFUtils @@ -22693,14 +22916,18 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE + [] ; + [] ; + [] ; + + [] ; + + [] ; + [] *-- Modulo _Version = 0 _SourceFile = '' + _I = 0 *-- Table Info + _TableName = '' _CodePage = 0 _Database = '' _FileType = '' @@ -22731,14 +22958,17 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE * taCodeLines (!@ IN ) Array de líneas del programa analizado * I (!@ IN/OUT) Número de línea en análisis * tnCodeLines (!@ IN ) Cantidad de líneas del programa analizado + * toFoxBin2Prg (@! IN ) Referencia de toFoxBin2Prg *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcLine, taCodeLines, I, tnCodeLines + LPARAMETERS tcLine, taCodeLines, I, tnCodeLines, toFoxBin2Prg TRY - LOCAL llBloqueEncontrado, lcPropName, lcValue, loEx AS EXCEPTION ; + LOCAL llBloqueEncontrado, lcPropName, lcValue, llFieldsEvaluated, llIndexesEvaluated ; + , loEx AS EXCEPTION ; , loFields AS CL_DBF_FIELDS OF 'FOXBIN2PRG.PRG' ; - , loIndexes AS CL_DBF_INDEXES OF 'FOXBIN2PRG.PRG' - STORE NULL TO loIndexes, loFields + , loIndexes AS CL_DBF_INDEXES OF 'FOXBIN2PRG.PRG' ; + , loRecords AS CL_DBF_RECORDS OF 'FOXBIN2PRG.PRG' + STORE NULL TO loIndexes, loFields, loRecords STORE '' TO lcPropName, lcValue IF LEFT(tcLine, LEN(C_TABLE_I)) == C_TABLE_I @@ -22755,13 +22985,28 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE CASE C_TABLE_F $ tcLine && Fin EXIT - CASE C_FIELDS_I $ tcLine + CASE NOT llFieldsEvaluated AND C_FIELDS_I $ tcLine loFields = ._Fields loFields.analyzeCodeBlock( @tcLine, @taCodeLines, @I, tnCodeLines ) + llFieldsEvaluated = .T. - CASE C_INDEXES_I $ tcLine + CASE NOT llIndexesEvaluated AND C_INDEXES_I $ tcLine loIndexes = ._Indexes loIndexes.analyzeCodeBlock( @tcLine, @taCodeLines, @I, tnCodeLines ) + llIndexesEvaluated = .T. + + CASE C_RECORDS_I $ tcLine + IF llFieldsEvaluated + * Pensado para poder llamar a este método 2 veces: + * > La 1ra.para evaluar Campos e Indices, y poder crear la estructura de la tabla + * al finalizar este paso. + * > La 2da.para cargar los registros, luego de que se haya creado la tabla, + * así se van volcando directamente y no se guardan en memoria. + EXIT + ENDIF + + loRecords = ._Records + loRecords.analyzeCodeBlock( @tcLine, @taCodeLines, @I, tnCodeLines, ._Fields, @toFoxBin2Prg ) OTHERWISE && Otro valor *-- Estructura a reconocer: @@ -22771,6 +23016,8 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE .ADDPROPERTY( '_' + lcPropName, lcValue ) ENDCASE ENDFOR + + ._I = I ENDWITH && THIS ENDIF @@ -22786,8 +23033,8 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE THROW FINALLY - STORE NULL TO loIndexes, loFields - RELEASE lcPropName, lcValue, loFields, loIndexes + STORE NULL TO loIndexes, loFields, loRecords + RELEASE lcPropName, lcValue, loFields, loIndexes, loRecords ENDTRY @@ -22814,15 +23061,20 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE #ENDIF TRY - LOCAL lcText, lcTableCFG, lcIndexKey, lcIndexFile, laConfig(1), lcValue, lcConfigItem ; + LOCAL lcText, lcIndexKey, lcIndexFile, laConfig(1), lcValue, lcConfigItem ; , lc_DBF_Conversion_Order, lc_DBF_Conversion_Condition, llExportData, laDirFile(1,5), lnFileCount ; , loEx AS EXCEPTION ; + , loFSO AS Scripting.FileSystemObject ; + , loTextStream AS Scripting.TextStream ; + , loDBF_CFG AS CL_DBF_CFG OF 'FOXBIN2PRG.PRG' ; , loRecords AS CL_DBF_RECORDS OF 'FOXBIN2PRG.PRG' ; , loFields AS CL_DBF_FIELDS OF 'FOXBIN2PRG.PRG' ; , loIndexes AS CL_DBF_INDEXES OF 'FOXBIN2PRG.PRG' + *** DH 06/02/2014: created variables LOCAL laFields[1], lnFieldCount - + loFSO = toFoxBin2Prg.o_FSO + loTextStream = toFoxBin2Prg.o_TextStream STORE NULL TO loIndexes, loFields, loRecords STORE 0 TO lnFileCount lcText = '' @@ -22849,37 +23101,18 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE lcText = lcText + loIndexes.toText( '', '', tc_InputFile, @toFoxBin2Prg ) *-- If table CFG exists, use it for DBF-specific configuration. FDBOZZO. 2014/06/15 - lcTableCFG = tc_InputFile + '.CFG' - lnFileCount = ADIR(laDirFile, lcTableCFG) + lnFileCount = toFoxBin2Prg.get_DBF_Configuration( FORCEEXT(tc_InputFile, 'DBF'), @loDBF_CFG, .T. ) - IF toFoxBin2Prg.DBF_Conversion_Support = 4 ; && BIN2PRG (DATA EXPORT FOR DIFF) - OR toFoxBin2Prg.DBF_Conversion_Support = 1 AND lnFileCount = 1 THEN - llExportData = .T. - ENDIF + DO CASE + CASE INLIST(toFoxBin2Prg.DBF_Conversion_Support, 4, 8) ; && BIN2TXT (DATA EXPORT FOR DIFF) + OR INLIST(toFoxBin2Prg.DBF_Conversion_Support, 1, 2) AND lnFileCount = 1 + *-- ASUNCIÓN: Si hay un archivo DBF.CFG, es porque se quiere exportar datos, si no, no debe crearse el DBF.CFG + llExportData = .T. + ENDCASE IF llExportData THEN IF lnFileCount = 1 - toFoxBin2Prg.writeLog() - toFoxBin2Prg.writeLog('* Found configuration file: ' + lcTableCFG) - - *-- Leer valores de configuración - FOR I = 1 TO ALINES( laConfig, FILETOSTR( lcTableCFG ), 1+4 ) - lcConfigItem = LOWER( laConfig(I) ) - - DO CASE - CASE INLIST( LEFT( lcConfigItem, 1 ), '*', '#', '/', "'" ) - LOOP - - CASE LEFT( lcConfigItem, 21 ) == LOWER('DBF_Conversion_Order:') - lc_DBF_Conversion_Order = ALLTRIM( SUBSTR( laConfig(I), 22 ) ) - toFoxBin2Prg.writeLog(' ' + JUSTFNAME(lcTableCFG) + ' -> DBF_Conversion_Order: ' + lc_DBF_Conversion_Order ) - - CASE LEFT( lcConfigItem, 25 ) == LOWER('DBF_Conversion_Condition:') - lc_DBF_Conversion_Condition = ALLTRIM( SUBSTR( laConfig(I), 26 ) ) - toFoxBin2Prg.writeLog(' ' + JUSTFNAME(lcTableCFG) + ' -> DBF_Conversion_Condition: ' + lc_DBF_Conversion_Condition ) - - ENDCASE - ENDFOR + lc_DBF_Conversion_Order = loDBF_CFG.DBF_Conversion_Order IF NOT EMPTY(lc_DBF_Conversion_Order) lcIndexFile = FORCEEXT(tc_InputFile,'IDX') @@ -22888,10 +23121,13 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE ENDIF ENDIF + ENDIF - *** DH 06/02/2014: added _Records + *** DH 06/02/2014: added _Records + IF llExportData loRecords = THIS._Records - FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) + *FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) + loTextStream.WriteLine( lcText ) && Replace VFP low-level file funcs.because the 8-16KB limit. loRecords.toText(@laFields, lnFieldCount, lc_DBF_Conversion_Condition, @toFoxBin2Prg) lcText = '' ENDIF @@ -22901,7 +23137,8 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE <<>> ENDTEXT - FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) + *FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) + loTextStream.WriteLine( lcText ) && Replace VFP low-level file funcs.because the 8-16KB limit. lcText = '' @@ -22913,12 +23150,13 @@ DEFINE CLASS CL_DBF_TABLE AS CL_CUS_BASE THROW FINALLY - STORE NULL TO loIndexes, loFields, loRecords - RELEASE loFields, loIndexes, loRecords IF NOT EMPTY(lcIndexFile) AND FILE(lcIndexFile) SET INDEX TO ERASE (lcIndexFile) ENDIF + + STORE NULL TO loIndexes, loFields, loRecords, loDBF_CFG, loTextStream + RELEASE loFields, loIndexes, loRecords, loDBF_CFG, loTextStream ENDTRY RETURN lcText @@ -23509,9 +23747,82 @@ DEFINE CLASS CL_DBF_RECORDS AS CL_COL_BASE * taCodeLines (@! IN ) Array de líneas del programa analizado * I (@! IN/OUT) Número de línea en análisis * tnCodeLines (@! IN ) Cantidad de líneas del programa analizado + * toFields (@! IN ) Estructura de los campos + * toFoxBin2Prg (@! IN ) Referencia de toFoxBin2Prg *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcLine, taCodeLines, I, tnCodeLines - *** DH 06/02/2014: not implemented + LPARAMETERS tcLine, taCodeLines, I, tnCodeLines, toFields, toFoxBin2Prg + + #IF .F. + LOCAL toFields AS CL_DBF_FIELDS OF 'FOXBIN2PRG.PRG' + LOCAL toFoxBin2Prg AS c_foxbin2prg OF 'FOXBIN2PRG.PRG' + #ENDIF + + TRY + LOCAL llBloqueEncontrado, lcPropName, lcValue, lcAlias, loEx AS EXCEPTION ; + , loRecord AS CL_DBF_RECORD OF 'FOXBIN2PRG.PRG' ; + , loRecordData as Object + STORE NULL TO loIndex + STORE '' TO lcPropName, lcValue, lcAlias + + IF LEFT(tcLine, LEN(C_RECORDS_I)) == C_RECORDS_I + llBloqueEncontrado = .T. + + WITH THIS AS CL_DBF_RECORDSS OF 'FOXBIN2PRG.PRG' + lcAlias = ALIAS() + CURSORSETPROP("Buffering", 3) + loRecord = NULL + loRecord = CREATEOBJECT("CL_DBF_RECORD") + + FOR I = I + 1 TO tnCodeLines + .set_Line( @tcLine, @taCodeLines, I ) + + DO CASE + CASE EMPTY( tcLine ) + LOOP + + CASE C_RECORDS_F $ tcLine && Fin + EXIT + + CASE '> <<>> <> ENDTEXT - FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) + *FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) + loTextStream.WriteLine( lcText ) && Replace VFP low-level file funcs.because the 8-16KB limit. lcText = '' loRecord = CREATEOBJECT('CL_DBF_RECORD') @@ -23554,16 +23869,16 @@ DEFINE CLASS CL_DBF_RECORDS AS CL_COL_BASE SCAN FOR &tc_DBF_Conversion_Condition. I = I + 1 lcText = loRecord.toText(@taFields, tnField_Count) - FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) - IF MOD(I,1000) = 0 THEN - toFoxBin2Prg.updateProgressbar( 'Exporting DBF Data...', 1+(I/lnReccount), 3, 2 ) - - IF MOD(I,10000) = 0 THEN - FFLUSH( toFoxBin2Prg.n_FileHandle, .T. ) - ENDIF + *FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) + loTextStream.WriteLine( lcText ) && Replace VFP low-level file funcs.because the 8-16KB limit. + IF MOD(I,100) = 0 OR LEN(lcText) > 8*1024 THEN + toFoxBin2Prg.updateProgressbar( 'Exporting DBF Data... ' + TRANSFORM(I) + '/' + TRANSFORM(lnReccount) + '', 1+(I/lnReccount), 3, 2 ) + DOEVENTS + *FFLUSH( toFoxBin2Prg.n_FileHandle, .T. ) ENDIF ENDSCAN + toFoxBin2Prg.updateProgressbar( 'Data exported! ', 1+(lnReccount/lnReccount), 3, 2 ) lcText = '' TEXT TO lcText ADDITIVE TEXTMERGE NOSHOW FLAGS 1+2 PRETEXT 1+2 @@ -23571,7 +23886,8 @@ DEFINE CLASS CL_DBF_RECORDS AS CL_COL_BASE <<>> ENDTEXT - FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) + *FWRITE( toFoxBin2Prg.n_FileHandle, lcText ) + loTextStream.WriteLine( lcText ) && Replace VFP low-level file funcs.because the 8-16KB limit. lcText = '' @@ -23584,8 +23900,8 @@ DEFINE CLASS CL_DBF_RECORDS AS CL_COL_BASE THROW FINALLY - STORE NULL TO loRecord - RELEASE loRecord + STORE NULL TO loRecord, loTextStream + RELEASE loRecord, loTextStream ENDTRY @@ -23602,6 +23918,8 @@ DEFINE CLASS CL_DBF_RECORD AS CL_CUS_BASE LOCAL THIS AS CL_DBF_RECORD OF 'FOXBIN2PRG.PRG' #ENDIF + _MEMBERDATA = [] ; + + [] PROCEDURE analyzeCodeBlock @@ -23611,9 +23929,143 @@ DEFINE CLASS CL_DBF_RECORD AS CL_CUS_BASE * taCodeLines (@! IN ) Array de líneas del programa analizado * I (@! IN/OUT) Número de línea en análisis * tnCodeLines (@! IN ) Cantidad de líneas del programa analizado + * toFields (@! IN ) Estructura de los campos *--------------------------------------------------------------------------------------------------- - LPARAMETERS tcLine, taCodeLines, I, tnCodeLines - *** DH 06/02/2014: not implemented + LPARAMETERS tcLine, taCodeLines, I, tnCodeLines, toFields + + #IF .F. + LOCAL toFields AS CL_DBF_FIELDS OF 'FOXBIN2PRG.PRG' + #ENDIF + + TRY + LOCAL llBloqueEncontrado, lcFieldName, lcValue, luValue, loEx AS EXCEPTION ; + , loField as CL_DBF_FIELD OF 'FOXBIN2PRG.PRG' + STORE '' TO lcFieldName, lcValue + + IF 'VALOR + lcFieldName = STREXTRACT( tcLine, '<', '>', 1, 0 ) + lcValue = STREXTRACT( tcLine, '<' + lcFieldName + '>', '', 1, 0+2 ) + loField = toFields.Item(lcFieldName) + + lcFieldType = loField._Type + llNoCPTran = CAST( loField._NoCPTran as Logical) + + DO CASE + CASE lcFieldType == 'L' && Logical (Boolean) + luValue = CAST(lcValue as Logical) + + CASE lcFieldType == 'G' && General (NOT SUPPORTED) + luValue = '' + + CASE lcFieldType == 'W' && Blob (Memo binario) + luValue = STRCONV(lcValue,14) + + CASE lcFieldType == 'Q' && Varbinary + luValue = STRCONV(lcValue,14) + + CASE lcFieldType == 'V' && Varchar + IF llNoCPTran + *-- If NoCPTran, then must encode in b64binary + luValue = STRCONV(lcValue,14) + ELSE + luValue = .Decode(lcValue) + ENDIF + + CASE lcFieldType == 'M' && Memo + IF llNoCPTran + *-- If NoCPTran, then must encode in b64binary + luValue = STRCONV(lcValue,14) + ELSE + * Si el memo es multi-línea, leer hasta encontrar el final ']]>' del CDATA. + luValue = '' + DO WHILE NOT EMPTY(lcValue) + IF ']]>' $ tcLine THEN + luValue = .Decode(lcValue, .T.) + EXIT + ELSE + I = I + 1 + .set_Line( @tcLine, @taCodeLines, I ) + lcValue = lcValue + CR_LF + tcLine + ENDIF + ENDDO + ENDIF + + CASE lcFieldType == 'D' && Date + luValue = CAST(lcValue as Date) + + CASE lcFieldType == 'T' && Datetime + luValue = CAST(lcValue as DateTime) + + CASE lcFieldType == 'Y' && Currency + luValue = CAST(lcValue as Currency) + + CASE lcFieldType == 'I' && Integer + luValue = CAST(lcValue as Integer) + + CASE lcFieldType == 'B' && Double + luValue = CAST(lcValue as Double) + + CASE lcFieldType == 'F' && Float + luValue = CAST(lcValue as Float) + + CASE lcFieldType == 'N' && Numeric + luValue = CAST(lcValue as Numeric) + + OTHERWISE && Asume 'C' && Character + IF llNoCPTran + *-- If NoCPTran, then must encode in b64binary + luValue = STRCONV(lcValue,14) + ELSE + luValue = .Decode(RTRIM(lcValue)) + ENDIF + + ENDCASE + + IF lcFieldType == 'G' + *-- Saltar campos General + ELSE + REPLACE (lcFieldName) WITH (luValue) + ENDIF + + ENDCASE + ENDFOR + ENDWITH && THIS + ENDIF + + CATCH TO loEx + IF loEx.ERRORNO = 1470 && Incorrect property name. + loEx.USERVALUE = 'I=' + TRANSFORM(I) + ', tcLine=' + TRANSFORM(tcLine) + ', lcFieldName=[' + TRANSFORM(lcFieldName) + '], Value=[' + TRANSFORM(lcValue) + ']' + ENDIF + + IF THIS.n_Debug > 0 AND _VFP.STARTMODE = 0 + SET STEP ON + ENDIF + + THROW + + FINALLY + STORE NULL TO loField + RELEASE loField + + ENDTRY + + RETURN llBloqueEncontrado ENDPROC @@ -23628,41 +24080,66 @@ DEFINE CLASS CL_DBF_RECORD AS CL_CUS_BASE EXTERNAL ARRAY taFields TRY - LOCAL I, lcText, loEx AS EXCEPTION, lcField, luValue, lcFieldType + LOCAL I, lcText, loEx AS EXCEPTION, lcField, luValue, lcFieldType, llNoCPTran lcText = '' WITH THIS AS CL_DBF_RECORD OF 'FOXBIN2PRG.PRG' *** FDBOZZO 2014/07/15: New "num" property invalidates the use of REGNUM field TEXT TO lcText TEXTMERGE NOSHOW FLAGS 1+2 PRETEXT 1+2 - <<>> <> + <<>> <> ENDTEXT FOR I = 1 TO tnField_Count lcField = taFields[I, 1] lcFieldType = taFields[I, 2] + llNoCPTran = taFields[I, 6] - *** FDBOZZO 2014/07/15: Added field restrictions on binary and general fields - DO CASE - CASE lcFieldType == 'G' - luValue = 'GENERAL FIELD NOT SUPPORTED' - *CASE lcFieldType == 'W' - * luValue = 'BLOB FIELD NOT SUPPORTED' - *CASE lcFieldType == 'Q' - * luValue = 'VARBINARY FIELD NOT SUPPORTED' - OTHERWISE + IF lcFieldType == 'G' + *-- Saltar campos de tipo General + ELSE luValue = EVALUATE(lcField) - ENDCASE - DO CASE - CASE taFields[I, 2] $ 'CMV' - luValue = TRIM(luValue) - IF .Encode(luValue) <> luValue - luValue = '' - ENDIF &&.Encode(luValue) <> luValue - ENDCASE - TEXT TO lcText TEXTMERGE NOSHOW flags 1+2 PRETEXT 1+2 additive - <<>> <<'<' + lcField + '>'>><><<''>> - ENDTEXT + DO CASE + CASE lcFieldType $ 'GWQVCM' AND luValue == '' ; && Vacío + OR lcFieldType $ 'DT' AND luValue == {} ; + OR lcFieldType $ 'YIBFN' AND luValue == 0 + + CASE lcFieldType == 'W' && Blob (Memo binario) + luValue = STRCONV(luValue,13) + + CASE lcFieldType == 'Q' && Varbinary + luValue = STRCONV(luValue,13) + + CASE lcFieldType == 'V' && Varchar + IF llNoCPTran THEN + *-- If NoCPTran, then must encode in b64binary + luValue = STRCONV(luValue,13) + ELSE + luValue = .Encode(luValue) + ENDIF + + CASE lcFieldType $ 'C' && Character + IF llNoCPTran THEN + *-- If NoCPTran, then must encode in b64binary + luValue = STRCONV(luValue,13) + ELSE + luValue = .Encode(RTRIM(luValue)) + ENDIF + + CASE lcFieldType $ 'M' && Memo + IF llNoCPTran THEN + *-- If NoCPTran, then must encode in b64binary + luValue = STRCONV(luValue,13) + ELSE + luValue = .Encode(RTRIM(luValue), .T.) + ENDIF + + ENDCASE + + TEXT TO lcText TEXTMERGE NOSHOW flags 1+2 PRETEXT 1+2 additive + <<>> <<'<' + lcField + '>'>><><<''>> + ENDTEXT + ENDIF NEXT TEXT TO lcText TEXTMERGE NOSHOW FLAGS 1+2 PRETEXT 1+2 additive @@ -23683,17 +24160,41 @@ DEFINE CLASS CL_DBF_RECORD AS CL_CUS_BASE ENDPROC PROCEDURE Encode - LPARAMETERS tcString + LPARAMETERS tcString, tl_isCDATA LOCAL lcString - lcString = STRTRAN(tcString, '&', '&') - lcString = STRTRAN(lcString, '>', '>') - lcString = STRTRAN(lcString, '<', '<') - lcString = STRTRAN(lcString, '"', '"') - lcString = STRTRAN(lcString, "'", ''') - lcString = STRTRAN(lcString, '/', '/') - lcString = STRTRAN(lcString, CHR(13), ' ') - lcString = STRTRAN(lcString, CHR(10), ' ') - lcString = STRTRAN(lcString, CHR(9), ' ') + IF tl_isCDATA THEN + *lcString = '', ']]]]>') + ']]>' + lcString = '', ']]>') + ']]>' + ELSE + lcString = STRTRAN(tcString, '&', '&') + lcString = STRTRAN(lcString, '>', '>') + lcString = STRTRAN(lcString, '<', '<') + lcString = STRTRAN(lcString, '"', '"') + lcString = STRTRAN(lcString, "'", ''') + lcString = STRTRAN(lcString, '/', '/') + lcString = STRTRAN(lcString, CHR(13), ' ') + lcString = STRTRAN(lcString, CHR(10), ' ') + lcString = STRTRAN(lcString, CHR(9), ' ') + ENDIF + RETURN lcString + ENDPROC + + PROCEDURE Decode + LPARAMETERS tcString, tl_isCDATA + LOCAL lcString + IF tl_isCDATA THEN + lcString = STRTRAN( STRTRAN( STREXTRACT( tcString, ''), '<![CDATA[', '') + ELSE + lcString = STRTRAN(tcString, ' ', CHR(9)) + lcString = STRTRAN(lcString, ' ', CHR(10)) + lcString = STRTRAN(lcString, ' ', CHR(13)) + lcString = STRTRAN(lcString, '/', '/') + lcString = STRTRAN(lcString, ''', "'") + lcString = STRTRAN(lcString, '"', '"') + lcString = STRTRAN(lcString, '<', '<') + lcString = STRTRAN(lcString, '>', '>') + lcString = STRTRAN(lcString, '&', '&') + ENDIF RETURN lcString ENDPROC @@ -27480,3 +27981,23 @@ DEFINE CLASS CL_LANG AS Custom ENDPROC ENDDEFINE + + + +DEFINE CLASS CL_DBF_CFG AS CUSTOM + _MEMBERDATA = [] ; + + [] ; + + [] ; + + [] ; + + [] + + #IF .F. + LOCAL THIS AS CL_DBF_CFG OF 'FOXBIN2PRG.PRG' + #ENDIF + + + *-- Configuration class. By default asumes master value, except when overriding one. + DBF_Conversion_Order = '' + DBF_Conversion_Condition = '' + DBF_Conversion_Support = 0 +ENDDEFINE