Skip to content

Commit

Permalink
Merge branch 'writeCsv'
Browse files Browse the repository at this point in the history
  • Loading branch information
cfsimplicity committed Nov 24, 2023
2 parents 74b3ddb + a50f437 commit 78ca81c
Show file tree
Hide file tree
Showing 22 changed files with 669 additions and 178 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Spreadsheet CFML

Standalone library for working with spreadsheets in CFML ([Lucee](http://lucee.org/) and Adobe ColdFusion), supporting all of ColdFusion's native spreadsheet functionality and much more besides.
Standalone library for working with spreadsheets and CSV in CFML ([Lucee](http://lucee.org/) and Adobe ColdFusion), supporting all of ColdFusion's native spreadsheet functionality and much more besides.

## Minimum Requirements

Expand Down
6 changes: 5 additions & 1 deletion Spreadsheet.cfc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
component accessors="true"{

//"static"
property name="version" default="3.11.1" setter="false";
property name="version" default="3.11.1-develop" setter="false";
property name="osgiLibBundleVersion" default="5.2.4.1" setter="false"; //first 3 octets = POI version; increment 4th with other jar updates
property name="osgiLibBundleSymbolicName" default="spreadsheet-cfml" setter="false";
property name="exceptionType" default="cfsimplicity.spreadsheet" setter="false";
Expand Down Expand Up @@ -1716,6 +1716,10 @@ component accessors="true"{
return this;
}

public any function writeCsv(){
return New objects.WriteCsv( this );
}

public Spreadsheet function writeFileFromQuery(
required query data
,required string filepath
Expand Down
3 changes: 1 addition & 2 deletions helpers/csv.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ component extends="base"{
return dataFromParser( parser );
}
finally{
if( local.KeyExists( "parser" ) )
parser.close();
getFileHelper().closeLocalFileOrStream( local, "parser" );
}
}

Expand Down
4 changes: 2 additions & 2 deletions helpers/query.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ component extends="base"{
catch( any exception ){
if( !exception.message CONTAINS "undefined" )
rethrow;
// ACF
return arguments.q.getColumnNames();
// ACF: the raw object can behave oddly with writeCsv().setQueryColumnsAsHeaderIfRequired(), hence re-casting as a CFML array
return ListToArray( ArrayToList( arguments.q.getColumnNames() ) );
}
}

Expand Down
120 changes: 120 additions & 0 deletions objects/BaseCsv.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
component accessors="true"{

property name="filepath";
property name="headerValues" type="array";
/* Java objects */
property name="format"; //org.apache.commons.csv.CSVFormat
/* Internal */
property name="library" setter="false";

public BaseCsv function init( required spreadsheetLibrary, string initialPredefinedFormat="DEFAULT" ){
variables.library = arguments.spreadsheetLibrary;
variables.format = createPredefinedFormat( arguments.initialPredefinedFormat );
return this;
}

/* Public builder API */
public BaseCsv function withPredefinedFormat( required string type ){
variables.format = createPredefinedFormat( arguments.type );
return this;
}

/* Format configuration */
public BaseCsv function withAllowMissingColumnNames( boolean state=true ){
variables.format = variables.format.builder().setAllowMissingColumnNames( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public BaseCsv function withAutoFlush( boolean state=true ){
variables.format = variables.format.builder().setAutoFlush( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public BaseCsv function withCommentMarker( required string marker ){
variables.format = variables.format.builder().setCommentMarker( JavaCast( "char", arguments.marker ) ).build();
return this;
}

public BaseCsv function withDelimiter( required string delimiter ){
if( variables.library.getCsvHelper().delimiterIsTab( arguments.delimiter ) ){
variables.format = createPredefinedFormat( "TDF" ); //tabs require several specific settings so use predefined format
return this;
}
variables.format = variables.format.builder().setDelimiter( JavaCast( "string", arguments.delimiter ) ).build();
return this;
}

public BaseCsv function withDuplicateHeaderMode( required string value ){
var mode = variables.library.createJavaObject( "org.apache.commons.csv.DuplicateHeaderMode" )[ JavaCast( "string", arguments.value ) ];
variables.format = variables.format.builder().setDuplicateHeaderMode( mode ).build();
return this;
}

public BaseCsv function withEscapeCharacter( required string character ){
variables.format = variables.format.builder().setEscape( JavaCast( "char", arguments.character ) ).build();
return this;
}

public BaseCsv function withHeader( required array header ){
variables.headerValues = arguments.header;
variables.format = variables.format.builder().setHeader( JavaCast( "string[]", arguments.header ) ).build();
return this;
}

public BaseCsv function withHeaderComments( required array comments ){
variables.format = variables.format.builder().setHeaderComments( JavaCast( "string[]", arguments.comments ) ).build();
return this;
}

public BaseCsv function withIgnoreEmptyLines( boolean state=true ){
variables.format = variables.format.builder().setIgnoreEmptyLines( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public BaseCsv function withIgnoreHeaderCase( boolean state=true ){
variables.format = variables.format.builder().setIgnoreHeaderCase( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public BaseCsv function withIgnoreSurroundingSpaces( boolean state=true ){
variables.format = variables.format.builder().setIgnoreSurroundingSpaces( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public BaseCsv function withNullString( required string value ){
variables.format = variables.format.builder().setNullString( JavaCast( "string", arguments.value ) ).build();
return this;
}

public BaseCsv function withQuoteCharacter( string character ){
variables.format = variables.format.builder().setQuote( JavaCast( "char", arguments.character ) ).build();
return this;
}

public BaseCsv function withQuoteMode( required string value ){
var mode = variables.library.createJavaObject( "org.apache.commons.csv.QuoteMode" )[ JavaCast( "string", arguments.value ) ];
variables.format = variables.format.builder().setQuoteMode( mode ).build();
return this;
}

public BaseCsv function withSkipHeaderRecord( boolean state=true ){
variables.format = variables.format.builder().setSkipHeaderRecord( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public BaseCsv function withTrailingDelimiter( boolean state=true ){
variables.format = variables.format.builder().setTrailingDelimiter( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public BaseCsv function withTrim( boolean state=true ){
variables.format = variables.format.builder().setTrim( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

//Private
private any function createPredefinedFormat( string type="DEFAULT" ){
return variables.library.createJavaObject( "org.apache.commons.csv.CSVFormat" )[ JavaCast( "string", arguments.type ) ];
}

}
113 changes: 4 additions & 109 deletions objects/ReadCsv.cfc
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
component accessors="true"{
component extends="BaseCsv" accessors="true"{

property name="filepath";
property name="firstRowIsHeader" type="boolean" default=false;
property name="headerValues" type="array";
property name="firstRowIsHeader" type="boolean" default="false";
property name="numberOfRowsToSkip" default=0;
property name="returnFormat" default="none";
property name="rowFilter";
property name="rowProcessor";
/* Java objects */
property name="format"; //org.apache.commons.csv.CSVFormat
/* Internal */
property name="library" setter="false";

public ReadCsv function init( required spreadsheetLibrary, required string filepath ){
variables.library = arguments.spreadsheetLibrary;
super.init( arguments.spreadsheetLibrary );
variables.library.getFileHelper()
.throwErrorIFfileNotExists( arguments.filepath )
.throwErrorIFnotCsvOrTextFile( arguments.filepath );
variables.filepath = arguments.filepath;
variables.format = createPredefinedFormat();
return this;
}

Expand All @@ -29,99 +22,6 @@ component accessors="true"{
return this;
}

public ReadCsv function withPredefinedFormat( required string type ){
variables.format = createPredefinedFormat( arguments.type );
return this;
}

/* Format configuration */
public ReadCsv function withAllowMissingColumnNames( boolean state=true ){
variables.format = variables.format.builder().setAllowMissingColumnNames( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public ReadCsv function withAutoFlush( boolean state=true ){
variables.format = variables.format.builder().setAutoFlush( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public ReadCsv function withCommentMarker( required string marker ){
variables.format = variables.format.builder().setCommentMarker( JavaCast( "char", arguments.marker ) ).build();
return this;
}

public ReadCsv function withDelimiter( required string delimiter ){
if( variables.library.getCsvHelper().delimiterIsTab( arguments.delimiter ) ){
variables.format = createPredefinedFormat( "TDF" ); //tabs require several specific settings so use predefined format
return this;
}
variables.format = variables.format.builder().setDelimiter( JavaCast( "string", arguments.delimiter ) ).build();
return this;
}

public ReadCsv function withDuplicateHeaderMode( required string value ){
var mode = variables.library.createJavaObject( "org.apache.commons.csv.DuplicateHeaderMode" )[ JavaCast( "string", arguments.value ) ];
variables.format = variables.format.builder().setDuplicateHeaderMode( mode ).build();
return this;
}

public ReadCsv function withEscapeCharacter( required string character ){
variables.format = variables.format.builder().setEscape( JavaCast( "char", arguments.character ) ).build();
return this;
}

public ReadCsv function withHeader( required array header ){
variables.headerValues = arguments.header;
variables.format = variables.format.builder().setHeader( JavaCast( "string[]", arguments.header ) ).build();
return this;
}

public ReadCsv function withHeaderComments( required array comments ){
variables.format = variables.format.builder().setHeaderComments( JavaCast( "string[]", arguments.comments ) ).build();
return this;
}

public ReadCsv function withIgnoreEmptyLines( boolean state=true ){
variables.format = variables.format.builder().setIgnoreEmptyLines( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public ReadCsv function withIgnoreHeaderCase( boolean state=true ){
variables.format = variables.format.builder().setIgnoreHeaderCase( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public ReadCsv function withIgnoreSurroundingSpaces( boolean state=true ){
variables.format = variables.format.builder().setIgnoreSurroundingSpaces( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public ReadCsv function withNullString( required string value ){
variables.format = variables.format.builder().setNullString( JavaCast( "string", arguments.value ) ).build();
return this;
}

public ReadCsv function withQuoteCharacter( string character ){
variables.format = variables.format.builder().setQuote( JavaCast( "char", arguments.character ) ).build();
return this;
}

public ReadCsv function withSkipHeaderRecord( boolean state=true ){
variables.format = variables.format.builder().setSkipHeaderRecord( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public ReadCsv function withTrailingDelimiter( boolean state=true ){
variables.format = variables.format.builder().setTrailingDelimiter( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

public ReadCsv function withTrim( boolean state=true ){
variables.format = variables.format.builder().setTrim( JavaCast( "boolean", arguments.state ) ).build();
return this;
}

// additional features
public ReadCsv function withFirstRowIsHeader( boolean state=true ){
variables.firstRowIsHeader = arguments.state;
return this;
Expand Down Expand Up @@ -178,8 +78,7 @@ component accessors="true"{
}
}
finally {
if( local.KeyExists( "parser" ) )
parser.close();
variables.library.getFileHelper().closeLocalFileOrStream( local, "parser" );
}
if( variables.returnFormat == "array" ){
useManuallySpecifiedHeaderForColumnsIfRequired( result );
Expand All @@ -199,8 +98,4 @@ component accessors="true"{
return variables.numberOfRowsToSkip && ( arguments.skippedRecords < variables.numberOfRowsToSkip );
}

private any function createPredefinedFormat( string type="DEFAULT" ){
return variables.library.createJavaObject( "org.apache.commons.csv.CSVFormat" )[ JavaCast( "string", arguments.type ) ];
}

}
Loading

0 comments on commit 78ca81c

Please sign in to comment.