feat(io): add csv parsing and serialization
This commit is contained in:
1 parent
a07f7e74f3
commit
9b8bc381a0
1 file changed
+102
@@ -0,0 +1,102 @@
|
||||
import 'address.dart';
|
||||
import 'sheet.dart';
|
||||
|
||||
List<List<String>> parseCsv(String input) {
|
||||
final rows = <List<String>>[];
|
||||
var field = StringBuffer();
|
||||
var record = <String>[];
|
||||
var inQuotes = false;
|
||||
var fieldStarted = false;
|
||||
var index = 0;
|
||||
|
||||
while (index < input.length) {
|
||||
final ch = input[index];
|
||||
if (inQuotes) {
|
||||
if (ch == '"') {
|
||||
if (index + 1 < input.length && input[index + 1] == '"') {
|
||||
field.write('"');
|
||||
index += 2;
|
||||
continue;
|
||||
}
|
||||
inQuotes = false;
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
field.write(ch);
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '"':
|
||||
inQuotes = true;
|
||||
fieldStarted = true;
|
||||
index++;
|
||||
case ',':
|
||||
record.add(field.toString());
|
||||
field = StringBuffer();
|
||||
fieldStarted = false;
|
||||
index++;
|
||||
case '\r':
|
||||
index++;
|
||||
case '\n':
|
||||
record.add(field.toString());
|
||||
rows.add(record);
|
||||
field = StringBuffer();
|
||||
record = <String>[];
|
||||
fieldStarted = false;
|
||||
index++;
|
||||
default:
|
||||
field.write(ch);
|
||||
fieldStarted = true;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (field.isNotEmpty || record.isNotEmpty || fieldStarted) {
|
||||
record.add(field.toString());
|
||||
rows.add(record);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
String encodeCsv(List<List<String>> rows) =>
|
||||
rows.map((record) => record.map(_encodeField).join(',')).join('\n');
|
||||
|
||||
String _encodeField(String value) {
|
||||
if (value.contains(',') || value.contains('"') || value.contains('\n') || value.contains('\r')) {
|
||||
return '"${value.replaceAll('"', '""')}"';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void importCsv(Sheet sheet, String input) {
|
||||
final rows = parseCsv(input);
|
||||
for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
||||
final record = rows[rowIndex];
|
||||
for (var colIndex = 0; colIndex < record.length; colIndex++) {
|
||||
final field = record[colIndex];
|
||||
if (field.isEmpty) continue;
|
||||
sheet.setCell(CellAddress(colIndex, rowIndex), field, recalculate: false);
|
||||
}
|
||||
}
|
||||
sheet.recalculate();
|
||||
}
|
||||
|
||||
String exportValues(Sheet sheet) => _export(sheet, formulas: false);
|
||||
|
||||
String exportFormulas(Sheet sheet) => _export(sheet, formulas: true);
|
||||
|
||||
String _export(Sheet sheet, {required bool formulas}) {
|
||||
final dimensions = sheet.dimensions();
|
||||
final rows = <List<String>>[];
|
||||
for (var row = 0; row < dimensions.rows; row++) {
|
||||
final record = <String>[];
|
||||
for (var col = 0; col < dimensions.cols; col++) {
|
||||
final address = CellAddress(col, row);
|
||||
record.add(formulas ? sheet.rawAt(address) : sheet.valueAt(address).display());
|
||||
}
|
||||
rows.add(record);
|
||||
}
|
||||
return encodeCsv(rows);
|
||||
}
|
||||
Reference in new issue
Block a user