Files
iotlcm/onelink-mock/internal/service/export_xlsx.go

162 lines
6.6 KiB
Go

package service
import (
"archive/zip"
"bytes"
"encoding/xml"
"fmt"
"strconv"
"strings"
)
func exportInboundCardsXLSX(cards []SIMCard) ([]byte, error) {
var buf bytes.Buffer
zw := zip.NewWriter(&buf)
files := map[string]string{
"[Content_Types].xml": contentTypesXML,
"_rels/.rels": rootRelsXML,
"xl/workbook.xml": workbookXML,
"xl/_rels/workbook.xml.rels": workbookRelsXML,
"xl/sharedStrings.xml": sharedStringsXML(),
"xl/styles.xml": stylesXML,
"xl/worksheets/sheet1.xml": sheetXML(cards),
}
for _, name := range []string{"[Content_Types].xml", "_rels/.rels", "xl/workbook.xml", "xl/_rels/workbook.xml.rels", "xl/sharedStrings.xml", "xl/styles.xml", "xl/worksheets/sheet1.xml"} {
w, err := zw.Create(name)
if err != nil {
return nil, err
}
if _, err := w.Write([]byte(files[name])); err != nil {
return nil, err
}
}
if err := zw.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func sheetXML(cards []SIMCard) string {
var b strings.Builder
b.WriteString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`)
b.WriteString(`<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
b.WriteString(`<dimension ref="A1:R`)
b.WriteString(strconv.Itoa(len(cards) + 1))
b.WriteString(`"/><sheetViews><sheetView tabSelected="true" workbookViewId="0"/></sheetViews>`)
b.WriteString(`<sheetFormatPr defaultRowHeight="15"/><cols><col min="1" max="18" width="9.140625" style="1"/></cols><sheetData>`)
writeSharedStringRow(&b, 1, len(inboundExportHeaders))
for i, card := range cards {
row := inboundExportRow(card)
values := make([]string, 0, len(inboundExportColumns))
for _, column := range inboundExportColumns {
values = append(values, row[column.Key])
}
writeSheetRow(&b, i+2, values)
}
b.WriteString(`</sheetData></worksheet>`)
return b.String()
}
func writeSharedStringRow(b *strings.Builder, rowNum, count int) {
b.WriteString(`<row r="`)
b.WriteString(strconv.Itoa(rowNum))
b.WriteString(`">`)
for i := 0; i < count; i++ {
ref := fmt.Sprintf("%s%d", columnName(i+1), rowNum)
b.WriteString(`<c r="`)
b.WriteString(ref)
b.WriteString(`" s="1" t="s"><v>`)
b.WriteString(strconv.Itoa(i))
b.WriteString(`</v></c>`)
}
b.WriteString(`</row>`)
}
func writeSheetRow(b *strings.Builder, rowNum int, values []string) {
b.WriteString(`<row r="`)
b.WriteString(strconv.Itoa(rowNum))
b.WriteString(`">`)
for i, value := range values {
ref := fmt.Sprintf("%s%d", columnName(i+1), rowNum)
b.WriteString(`<c r="`)
b.WriteString(ref)
b.WriteString(`" s="1" t="inlineStr"><is><t>`)
b.WriteString(xmlEscape(value))
b.WriteString(`</t></is></c>`)
}
b.WriteString(`</row>`)
}
func sharedStringsXML() string {
var b strings.Builder
b.WriteString(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`)
b.WriteString(`<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="`)
b.WriteString(strconv.Itoa(len(inboundExportHeaders)))
b.WriteString(`" uniqueCount="`)
b.WriteString(strconv.Itoa(len(inboundExportHeaders)))
b.WriteString(`">`)
for _, header := range inboundExportHeaders {
b.WriteString(`<si><t>`)
b.WriteString(xmlEscape(header))
b.WriteString(`</t></si>`)
}
b.WriteString(`</sst>`)
return b.String()
}
func columnName(index int) string {
var out []byte
for index > 0 {
index--
out = append([]byte{byte('A' + index%26)}, out...)
index /= 26
}
return string(out)
}
func xmlEscape(value string) string {
var b strings.Builder
_ = xml.EscapeText(&b, []byte(value))
return b.String()
}
const contentTypesXML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
</Types>`
const rootRelsXML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
</Relationships>`
const workbookXML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<sheets>
<sheet name="Sheet1" sheetId="1" r:id="rId1"/>
</sheets>
</workbook>`
const workbookRelsXML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>
</Relationships>`
const stylesXML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<fonts count="1"><font><sz val="11"/><color theme="1"/><name val="Calibri"/><family val="2"/></font></fonts>
<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>
<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>
<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>
<cellXfs count="2"><xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/><xf numFmtId="49" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/></cellXfs>
<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>
<dxfs count="0"/><tableStyles count="0" defaultPivotStyle="PivotStyleLight16" defaultTableStyle="TableStyleMedium2"/>
</styleSheet>`