diff --git a/CHANGELOG.md b/CHANGELOG.md index fb2a6a0..9b73c6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- param tryColumnType, will try to format column by type. + ## [1.0.1] - 2024-07-16 ### Added diff --git a/README.md b/README.md index 8321e50..fa5fb7d 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Tool export query in CSV and XLS / XLSX format - + diff --git a/src/main/java/org/fugerit/java/query/export/catalog/QueryConfig.java b/src/main/java/org/fugerit/java/query/export/catalog/QueryConfig.java index 523c59d..755008e 100644 --- a/src/main/java/org/fugerit/java/query/export/catalog/QueryConfig.java +++ b/src/main/java/org/fugerit/java/query/export/catalog/QueryConfig.java @@ -29,5 +29,7 @@ public class QueryConfig extends BasicIdConfigType { @Getter @Setter private String xlsTemplate; @Getter @Setter private String createPath; + + @Getter @Setter private String tryColumnType; } diff --git a/src/main/java/org/fugerit/java/query/export/catalog/QueryConfigCatalog.java b/src/main/java/org/fugerit/java/query/export/catalog/QueryConfigCatalog.java index 97e98e8..768a73e 100644 --- a/src/main/java/org/fugerit/java/query/export/catalog/QueryConfigCatalog.java +++ b/src/main/java/org/fugerit/java/query/export/catalog/QueryConfigCatalog.java @@ -96,6 +96,9 @@ public static void handle( Connection conn, QueryConfig queryConfig ) throws IOE } else { throw new ConfigRuntimeException( "Unsuppoorted format : "+format ); } + if ( StringUtils.isNotEmpty( queryConfig.getTryColumnType() ) ) { + config.setTryColumnType( BooleanUtils.isTrue( queryConfig.getTryColumnType() ) ); + } config.getParams().putAll( params ); QueryExportFacade.export(config); } diff --git a/src/main/java/org/fugerit/java/query/export/facade/QueryExportConfig.java b/src/main/java/org/fugerit/java/query/export/facade/QueryExportConfig.java index f19b964..9a9e607 100644 --- a/src/main/java/org/fugerit/java/query/export/facade/QueryExportConfig.java +++ b/src/main/java/org/fugerit/java/query/export/facade/QueryExportConfig.java @@ -4,6 +4,8 @@ import java.sql.Connection; import java.util.Properties; +import lombok.Getter; +import lombok.Setter; import org.fugerit.java.query.export.meta.BasicObjectFormat; public class QueryExportConfig { @@ -47,6 +49,7 @@ public QueryExportConfig(String format, char separator, OutputStream output, Con this.query = query; this.exportHeader = exportHeader; this.params = new Properties(); + this.tryColumnType = false; } private String format; @@ -126,5 +129,14 @@ public BasicObjectFormat getObjectFormat() { public void setObjectFormat(BasicObjectFormat objectFormat) { this.objectFormat = objectFormat; } + + /* + * if set to true, by default : + * string - is unchanged + * number - dependent on outout format, for excel : #,### + * date - dependent on outout format, for excel : m/d/yy h:mm + */ + @Getter @Setter + private boolean tryColumnType; } diff --git a/src/main/java/org/fugerit/java/query/export/facade/QueryExportFacade.java b/src/main/java/org/fugerit/java/query/export/facade/QueryExportFacade.java index e59a213..8d3499e 100644 --- a/src/main/java/org/fugerit/java/query/export/facade/QueryExportFacade.java +++ b/src/main/java/org/fugerit/java/query/export/facade/QueryExportFacade.java @@ -32,10 +32,11 @@ private QueryExportFacade() {} public static final String ARG_XLS_RESIZE = "xls-resize"; public static final String ARG_XLS_RESIZE_DEFAULT = "false"; - + public static boolean registerHandler( String type ) { boolean ok = false; try { + QueryExportHandler handler = (QueryExportHandler)ClassHelper.newInstance( type ); setGet( null, handler ); ok = true; diff --git a/src/main/java/org/fugerit/java/query/export/facade/format/QueryExportHandlerXLSBase.java b/src/main/java/org/fugerit/java/query/export/facade/format/QueryExportHandlerXLSBase.java index fb33cf8..8307c92 100644 --- a/src/main/java/org/fugerit/java/query/export/facade/format/QueryExportHandlerXLSBase.java +++ b/src/main/java/org/fugerit/java/query/export/facade/format/QueryExportHandlerXLSBase.java @@ -6,10 +6,7 @@ import java.io.InputStream; import java.util.Iterator; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.*; import org.fugerit.java.core.function.SafeFunction; import org.fugerit.java.core.lang.helpers.BooleanUtils; import org.fugerit.java.query.export.facade.QueryExportConfig; @@ -34,14 +31,29 @@ protected QueryExportHandlerXLSBase(String format) { super(format); } - private void addRow( Iterator currentRecord, Sheet sheet, int index ) { + private void addRow( Workbook workbook, Iterator currentRecord, Sheet sheet, int index, QueryExportConfig config ) { int col = 0; Row row = sheet.createRow( index ); while ( currentRecord.hasNext() ) { MetaField field = currentRecord.next(); - String value = field.getStringValue(); Cell cell = row.createCell( col ); - cell.setCellValue( value ); + if ( config.isTryColumnType() && field.getType() != MetaField.TYPE_STRING ) { + if ( field.getType() == MetaField.TYPE_DATE ) { + DataFormat format = workbook.createDataFormat(); + CellStyle style = workbook.createCellStyle(); + style.setDataFormat( format.getFormat( "m/d/yy h:mm" ) ); + cell.setCellValue( field.getTimestampValue() ); + cell.setCellStyle(style); + } else if ( field.getType() == MetaField.TYPE_NUMBER ) { + DataFormat format = workbook.createDataFormat(); + CellStyle style = workbook.createCellStyle(); + style.setDataFormat( format.getFormat( "#,###" ) ); + cell.setCellValue( field.getNumberValue() ); + cell.setCellStyle(style); + } + } else { + cell.setCellValue( field.getStringValue() ); + } col++; } } @@ -71,7 +83,7 @@ public int export( QueryExportConfig config, MetaResult meta ) { if ( xlsTemplate == null ) { sheet = workbook.createSheet(); if ( meta.hasHeader() ) { - addRow( meta.headerIterator() , sheet, 0 ); + addRow( workbook, meta.headerIterator() , sheet, 0, config ); } } else { sheet = workbook.getSheetAt( 0 ); @@ -80,7 +92,7 @@ public int export( QueryExportConfig config, MetaResult meta ) { Iterator itRec = meta.recordIterator(); while ( itRec.hasNext() ) { MetaRecord currentRecord = itRec.next(); - addRow( currentRecord.fieldIterator() , sheet, index ); + addRow( workbook, currentRecord.fieldIterator() , sheet, index, config ); index++; } if ( BooleanUtils.isTrue( config.getParams().getProperty( QueryExportFacade.ARG_XLS_RESIZE ) ) ) { diff --git a/src/main/java/org/fugerit/java/query/export/meta/BasicMetaField.java b/src/main/java/org/fugerit/java/query/export/meta/BasicMetaField.java index 7cb1bb7..964b16e 100644 --- a/src/main/java/org/fugerit/java/query/export/meta/BasicMetaField.java +++ b/src/main/java/org/fugerit/java/query/export/meta/BasicMetaField.java @@ -1,11 +1,36 @@ package org.fugerit.java.query.export.meta; +import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; -@AllArgsConstructor +import java.sql.Timestamp; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) public class BasicMetaField implements MetaField { - @Getter private String stringValue; + public BasicMetaField(String stringValue) { + this( TYPE_STRING, stringValue, null, null ); + } + + public BasicMetaField(String stringValue, Long longValue) { + this( TYPE_NUMBER, stringValue, longValue, null ); + } + + public BasicMetaField(String stringValue, Timestamp timestampValue) { + this( TYPE_DATE, stringValue, null, timestampValue ); + } + + @Getter + private int type; + + @Getter + private String stringValue; + + @Getter + private Long numberValue; + + @Getter + private Timestamp timestampValue; } diff --git a/src/main/java/org/fugerit/java/query/export/meta/BasicMetaRSE.java b/src/main/java/org/fugerit/java/query/export/meta/BasicMetaRSE.java index fddce99..7e4d786 100644 --- a/src/main/java/org/fugerit/java/query/export/meta/BasicMetaRSE.java +++ b/src/main/java/org/fugerit/java/query/export/meta/BasicMetaRSE.java @@ -3,7 +3,9 @@ import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Date; import java.util.List; import org.fugerit.java.core.db.dao.RSExtractor; @@ -59,8 +61,13 @@ public MetaRecord extractNext(ResultSet rs) throws SQLException { Object current = rs.getObject( k+1 ); SafeFunction.apply( () -> { String value = this.getFormat().format( current ); - MetaField field = new BasicMetaField( value ); - fields.add( field ); + if ( current instanceof Number ) { + fields.add( new BasicMetaField( value, ((Number)current).longValue() ) ); + } else if ( current instanceof Date) { + fields.add( new BasicMetaField( value, new Timestamp( ((Date)current).getTime() ) ) ); + } else { + fields.add( new BasicMetaField( value ) ); + } } ); } return new BasicMetaRecord( fields ); diff --git a/src/main/java/org/fugerit/java/query/export/meta/MetaField.java b/src/main/java/org/fugerit/java/query/export/meta/MetaField.java index 033ac1a..cf922fb 100644 --- a/src/main/java/org/fugerit/java/query/export/meta/MetaField.java +++ b/src/main/java/org/fugerit/java/query/export/meta/MetaField.java @@ -1,7 +1,27 @@ package org.fugerit.java.query.export.meta; +import java.sql.Timestamp; + public interface MetaField { - public String getStringValue(); - + public static final int TYPE_STRING = 1; + + public static final int TYPE_NUMBER = 2; + + public static final int TYPE_DATE = 3; + + String getStringValue(); + + default int getType() { + return TYPE_STRING; + } + + default Long getNumberValue() { + return null; + } + + default Timestamp getTimestampValue() { + return null; + } + } diff --git a/src/test/java/test/org/fugerit/java/query/export/tool/TestBase.java b/src/test/java/test/org/fugerit/java/query/export/tool/TestBase.java index 7e715d3..98696dc 100644 --- a/src/test/java/test/org/fugerit/java/query/export/tool/TestBase.java +++ b/src/test/java/test/org/fugerit/java/query/export/tool/TestBase.java @@ -29,11 +29,11 @@ public synchronized static void initDatabase() throws SQLException { if ( !init ) { try (Connection connection = getConnection(); Statement statement = connection.createStatement();) { statement.execute("CREATE TABLE test_export (id INT NOT NULL, name VARCHAR(50) NOT NULL," - + "email VARCHAR(50) NOT NULL, PRIMARY KEY (id))"); + + "email VARCHAR(50) NOT NULL, testdate DATE, PRIMARY KEY (id))"); connection.commit(); - statement.executeUpdate("INSERT INTO test_export VALUES (1001,'FieldA1', 'FieldB1')"); - statement.executeUpdate("INSERT INTO test_export VALUES (1002,'FieldA2', 'FieldB2')"); - statement.executeUpdate("INSERT INTO test_export VALUES (1003,'FieldA3', 'FieldB3')"); + statement.executeUpdate("INSERT INTO test_export VALUES (1001,'FieldA1', 'FieldB1', '2024-11-02')"); + statement.executeUpdate("INSERT INTO test_export VALUES (1002,'FieldA2', 'FieldB2', '2024-11-03')"); + statement.executeUpdate("INSERT INTO test_export VALUES (1003,'FieldA3', 'FieldB3', '2024-11-04')"); connection.commit(); init = true; } diff --git a/src/test/java/test/org/fugerit/java/query/export/tool/TestExport.java b/src/test/java/test/org/fugerit/java/query/export/tool/TestExport.java index d87cd66..a7325f6 100644 --- a/src/test/java/test/org/fugerit/java/query/export/tool/TestExport.java +++ b/src/test/java/test/org/fugerit/java/query/export/tool/TestExport.java @@ -12,11 +12,15 @@ import org.junit.Test; public class TestExport extends TestBase { - + private boolean testWorkerSingle( String format, Properties params ) { + return this.testWorkerSingle( format, params, false, "" ); + } + + private boolean testWorkerSingle( String format, Properties params, boolean tryColumnType, String fileNameAppend ) { return SafeFunction.get( () -> { logger.info( "test start" ); - File outputFile = new File( "target/test_export_"+params.size()+"."+format ); + File outputFile = new File( "target/test_export_"+fileNameAppend+params.size()+"."+format ); try ( FileOutputStream fos = new FileOutputStream( outputFile ) ) { String query = " SELECT * FROM test_export "; QueryExportConfig config = null; @@ -31,6 +35,7 @@ private boolean testWorkerSingle( String format, Properties params ) { } else { config = new QueryExportConfig(format, ',', fos, getConnection(), query); // fail } + config.setTryColumnType( tryColumnType ); config.getParams().putAll( params ); QueryExportFacade.export( config ); logger.info( "test end" ); @@ -62,6 +67,13 @@ public void testXlsx() { Assert.assertTrue( ok ); } + @Test + public void testXlsxTryType() { + Properties params = new Properties(); + boolean ok = this.testWorkerSingle( QueryExportFacade.FORMAT_XLSX, params, true, "try_column_type_" ); + Assert.assertTrue( ok ); + } + @Test public void testXls() { Properties params = new Properties(); diff --git a/src/test/java/test/org/fugerit/java/query/export/tool/TestModel.java b/src/test/java/test/org/fugerit/java/query/export/tool/TestModel.java new file mode 100644 index 0000000..aa79ecd --- /dev/null +++ b/src/test/java/test/org/fugerit/java/query/export/tool/TestModel.java @@ -0,0 +1,23 @@ +package test.org.fugerit.java.query.export.tool; + +import org.fugerit.java.query.export.meta.MetaField; +import org.junit.Assert; +import org.junit.Test; + +public class TestModel { + + @Test + public void testMetaField() { + MetaField field = new MetaField() { + @Override + public String getStringValue() { + return ""; + } + }; + Assert.assertNull( field.getNumberValue() ); + Assert.assertNull( field.getTimestampValue() ); + Assert.assertEquals( "", field.getStringValue() ); + Assert.assertEquals( MetaField.TYPE_STRING, field.getType() ); + } + +} diff --git a/src/test/resources/sample/query-catalog-sample.xml b/src/test/resources/sample/query-catalog-sample.xml index 887b9c9..4fdf526 100644 --- a/src/test/resources/sample/query-catalog-sample.xml +++ b/src/test/resources/sample/query-catalog-sample.xml @@ -4,7 +4,7 @@ - +