Files
herolib/lib/biz/spreadsheet/sheet_export_csv.v
2025-11-30 08:59:38 +01:00

86 lines
2.3 KiB
V

module spreadsheet
import os
import incubaid.herolib.core.pathlib
@[params]
pub struct ExportCSVArgs {
pub mut:
path string
include_empty bool // whether to include empty cells or not
separator string = '|' // separator character for CSV
}
// format_csv_value formats a value for CSV export, handling special characters
fn format_csv_value(val string, separator string) string {
// If value contains the separator, quotes, or newlines, wrap in quotes and escape quotes
if val.contains(separator) || val.contains('"') || val.contains('\n') {
return '"${val.replace('"', '""')}"'
}
return val
}
// format_number_csv formats a number for CSV export
fn format_number_csv(val f64, include_empty bool) string {
if val < 0.001 && val > -0.001 {
if include_empty {
return '0'
}
return ''
}
if val >= 1000.0 || val <= -1000.0 {
return int(val).str()
}
// Format small numbers with up to 3 decimal places, removing trailing zeros
str := '${val:.3f}'
// Remove trailing zeros and decimal point if needed
if str.contains('.') {
str_trimmed := str.trim_right('0').trim_right('.')
return str_trimmed
}
return str
}
// export_csv exports the sheet data to a CSV file with pipe separation
pub fn (mut s Sheet) export_csv(args ExportCSVArgs) !string {
mut result := []string{}
mut separator := args.separator
// Add headers
mut header_row := ['Name', 'Description', 'AggregateType', 'Tags', 'Subgroup']
header_row << s.header()!
result << header_row.map(format_csv_value(it, separator)).join(separator)
// Add rows
for _, row in s.rows {
mut row_data := [
format_csv_value(row.name, separator),
format_csv_value(row.description, separator),
format_csv_value(row.aggregatetype.str(), separator),
format_csv_value(row.tags, separator),
format_csv_value(row.subgroup, separator),
]
for cell in row.cells {
if cell.empty && !args.include_empty {
row_data << ''
} else {
val_str := format_number_csv(cell.val, args.include_empty)
row_data << format_csv_value(val_str, separator)
}
}
result << row_data.join(separator)
}
if args.path.len > 0 {
mut p := pathlib.get_file(
path: args.path.replace('~', os.home_dir())
create: true
delete: true
)!
p.write(result.join('\n'))!
}
return result.join('\n')
}