Skip to content

Commit 7102fea

Browse files
committed
feat(Ng2Csv.service): allow configuration of output values for null and undefined values
fix issue #9
1 parent aabb4e4 commit 7102fea

4 files changed

Lines changed: 108 additions & 2 deletions

File tree

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,16 @@ csvConfig.includeHeaderRow = false;
9595
this.ng2Csv.download(myData, 'file.csv', undefined, csvConfig);
9696
```
9797
98+
### Null or undefined values
99+
You can control how `null` or `undefined` values are written out in config.
100+
```
101+
import { CsvConfiguration } from 'ng2csv';
102+
// ...
103+
const csvConfig = new CsvConfiguration();
104+
csvConfig.outputValueForNull = 'NULL';
105+
csvConfig.outputValueForUndefined = 'UNDEFINED';
106+
```
107+
98108
## Contributions welcome!
99109
If you have a feature or improvement you would like to see included, please raise an issue or a PR and I will review.
100110

src/CsvConfiguration.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ export class CsvConfiguration {
33
public quote: string = '"';
44
public newLine: string = '\r\n';
55
public includeHeaderLine: boolean = true;
6+
public outputValueForNull: string = '';
7+
public outputValueForUndefined: string = '';
68
}

src/Ng2Csv.service.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Injectable } from '@angular/core';
2-
import * as FileSaver from 'file-saver';
2+
import { saveAs } from 'file-saver';
33
import { AutoCsvRowMapper } from './AutoCsvRowMapper';
44
import { CsvConfiguration } from './CsvConfiguration';
55
import { ICsvRowMapper } from './ICsvRowMapper';
@@ -17,7 +17,7 @@ export class Ng2CsvService {
1717
+ (config.includeHeaderLine ? 'present' : 'absent');
1818

1919
const csvBlob: Blob = new Blob([csvData], { type: mimeType });
20-
FileSaver.saveAs(csvBlob, filename, true);
20+
saveAs(csvBlob, filename, true);
2121
}
2222

2323
public convertToCsv<T>(
@@ -42,13 +42,30 @@ export class Ng2CsvService {
4242

4343
for (const row of data) {
4444
rows.push(csvRowMapper.map(row)
45+
.map(x => this.mapNullOrUndefinedValues(x, config))
4546
.map(x => this.escapeRowValue(x, config))
4647
.join(config.delimiter));
4748
}
4849

4950
return rows.join(config.newLine);
5051
}
5152

53+
private mapNullOrUndefinedValues(
54+
value: string,
55+
config: CsvConfiguration): string {
56+
switch (value) {
57+
case null: {
58+
return config.outputValueForNull;
59+
}
60+
case undefined: {
61+
return config.outputValueForUndefined;
62+
}
63+
default: {
64+
return value;
65+
}
66+
}
67+
}
68+
5269
private escapeQuotes(
5370
value: string,
5471
quoteChar: string): string {

test/Ng2Csv.service.spec.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,82 @@ describe('Ng2CsvService', () => {
7272
'"id","name"\r\n'
7373
+ '"1,000","Smith, Alice"\r\n2,"""Bob"" Smith"');
7474
}));
75+
76+
it('should output null values as configured value',
77+
inject([Ng2CsvService], (ng2CsvService: Ng2CsvService) => {
78+
const config = new CsvConfiguration();
79+
config.outputValueForNull = 'NULL';
80+
81+
const csv = ng2CsvService.convertToCsv([
82+
{
83+
id: 'X1000',
84+
name: 'Alice'
85+
},
86+
{
87+
id: null,
88+
name: 'Bob'
89+
}
90+
],
91+
new OrderedProjectionCsvRowMapper([
92+
['Id', x => x.id],
93+
['Name', x => x.name]
94+
]),
95+
config);
96+
97+
expect(csv).toBe(
98+
'"Id","Name"\r\n'
99+
+ 'X1000,Alice\r\nNULL,Bob'
100+
);
101+
}));
102+
103+
it('should output undefined values as configured value',
104+
inject([Ng2CsvService], (ng2CsvService: Ng2CsvService) => {
105+
const config = new CsvConfiguration();
106+
config.outputValueForUndefined = 'UNDEFINED';
107+
108+
const csv = ng2CsvService.convertToCsv([
109+
{
110+
id: 'X1000',
111+
name: 'Alice'
112+
},
113+
{
114+
id: undefined,
115+
name: 'Bob'
116+
}
117+
],
118+
new OrderedProjectionCsvRowMapper([
119+
['Id', x => x.id],
120+
['Name', x => x.name]
121+
]),
122+
config);
123+
124+
expect(csv).toBe(
125+
'"Id","Name"\r\n'
126+
+ 'X1000,Alice\r\nUNDEFINED,Bob'
127+
);
128+
}));
129+
130+
it('should output null/undefined values as empty string by default',
131+
inject([Ng2CsvService], (ng2CsvService: Ng2CsvService) => {
132+
const csv = ng2CsvService.convertToCsv([
133+
{
134+
id: 'X1000',
135+
name: null
136+
},
137+
{
138+
id: undefined,
139+
name: 'Bob'
140+
}
141+
],
142+
new OrderedProjectionCsvRowMapper([
143+
['Id', x => x.id],
144+
['Name', x => x.name]
145+
]));
146+
147+
expect(csv).toBe(
148+
'"Id","Name"\r\n'
149+
+ 'X1000,\r\n,Bob'
150+
);
151+
}));
75152
});
76153
});

0 commit comments

Comments
 (0)