首次提交: OnebotCatalog 项目代码与文档(含 NX 按需生成服务二期、后台、一键启动)
This commit is contained in:
103
sample-data/tools/gen-xlsx.ps1
Normal file
103
sample-data/tools/gen-xlsx.ps1
Normal file
@@ -0,0 +1,103 @@
|
||||
# 把 params.csv 生成一份真正的 .xlsx (最小 OOXML 结构, 免依赖 Excel)
|
||||
# 用法: powershell -NoProfile -ExecutionPolicy Bypass -File tools\gen-xlsx.ps1
|
||||
# 说明: 仅供查看格式参考; Builder 导入用 CSV (Excel 里另存为 CSV 即可)。
|
||||
param(
|
||||
[string]$Csv = (Join-Path $PSScriptRoot '..\onb-sc\params.csv'),
|
||||
[string]$Out = (Join-Path $PSScriptRoot '..\onb-sc\params.xlsx')
|
||||
)
|
||||
|
||||
Add-Type -AssemblyName System.IO.Compression
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
|
||||
function Xml-Esc([string]$s) {
|
||||
return $s.Replace('&', '&').Replace('<', '<').Replace('>', '>').Replace('"', '"')
|
||||
}
|
||||
|
||||
# 列号 → 列字母 (A..Z, AA..)
|
||||
function Col-Name([int]$i) {
|
||||
$name = ''
|
||||
$n = $i + 1
|
||||
while ($n -gt 0) {
|
||||
$r = ($n - 1) % 26
|
||||
$name = [char](65 + $r) + $name
|
||||
$n = [int](($n - 1) / 26)
|
||||
}
|
||||
return $name
|
||||
}
|
||||
|
||||
$rows = Get-Content $Csv | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
|
||||
if ($rows.Count -lt 1) { Write-Output "CSV 为空"; exit 1 }
|
||||
|
||||
# ---- sheet1.xml ----
|
||||
$sb = New-Object System.Text.StringBuilder
|
||||
[void]$sb.Append('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>')
|
||||
[void]$sb.Append('<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>')
|
||||
for ($r = 0; $r -lt $rows.Count; $r++) {
|
||||
$cells = $rows[$r].Split(',')
|
||||
[void]$sb.Append('<row r="' + ($r + 1) + '">')
|
||||
for ($c = 0; $c -lt $cells.Count; $c++) {
|
||||
$val = $cells[$c]
|
||||
$ref = (Col-Name $c) + ($r + 1)
|
||||
$num = 0.0
|
||||
if ($r -gt 0 -and [double]::TryParse($val, [System.Globalization.NumberStyles]::Float, [System.Globalization.CultureInfo]::InvariantCulture, [ref]$num)) {
|
||||
[void]$sb.Append('<c r="' + $ref + '"><v>' + $val + '</v></c>')
|
||||
} else {
|
||||
[void]$sb.Append('<c r="' + $ref + '" t="inlineStr"><is><t xml:space="preserve">' + (Xml-Esc $val) + '</t></is></c>')
|
||||
}
|
||||
}
|
||||
[void]$sb.Append('</row>')
|
||||
}
|
||||
[void]$sb.Append('</sheetData></worksheet>')
|
||||
$sheetXml = $sb.ToString()
|
||||
|
||||
# ---- 其余固定部件 ----
|
||||
$contentTypes = '<?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"/>' +
|
||||
'</Types>'
|
||||
$rels = '<?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>'
|
||||
$workbook = '<?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="SC系列" sheetId="1" r:id="rId1"/></sheets></workbook>'
|
||||
$workbookRels = '<?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"/>' +
|
||||
'</Relationships>'
|
||||
|
||||
$enc = New-Object System.Text.UTF8Encoding($false)
|
||||
|
||||
# 手动 CreateEntry 控制条目名 (OOXML 规范要求正斜杠, CreateFromDirectory 会生成反斜杠)
|
||||
if (Test-Path $Out) { Remove-Item $Out -Force }
|
||||
$zip = [System.IO.Compression.ZipFile]::Open($Out, [System.IO.Compression.ZipArchiveMode]::Create)
|
||||
function Add-Entry([string]$name, [string]$content) {
|
||||
$e = $zip.CreateEntry($name)
|
||||
$sw = New-Object System.IO.StreamWriter($e.Open(), $enc)
|
||||
$sw.Write($content)
|
||||
$sw.Close()
|
||||
}
|
||||
Add-Entry '[Content_Types].xml' $contentTypes
|
||||
Add-Entry '_rels/.rels' $rels
|
||||
Add-Entry 'xl/workbook.xml' $workbook
|
||||
Add-Entry 'xl/_rels/workbook.xml.rels' $workbookRels
|
||||
Add-Entry 'xl/worksheets/sheet1.xml' $sheetXml
|
||||
$zip.Dispose()
|
||||
|
||||
# ---- 自检: 重新打开并校验 XML 结构 ----
|
||||
$z = [System.IO.Compression.ZipFile]::OpenRead($Out)
|
||||
$ok = $true
|
||||
foreach ($part in @('[Content_Types].xml', '_rels/.rels', 'xl/workbook.xml', 'xl/_rels/workbook.xml.rels', 'xl/worksheets/sheet1.xml')) {
|
||||
try {
|
||||
$e = $z.GetEntry($part)
|
||||
$sr = New-Object System.IO.StreamReader($e.Open())
|
||||
$null = [xml]$sr.ReadToEnd()
|
||||
$sr.Close()
|
||||
} catch { Write-Output ("XML 无效: " + $part); $ok = $false }
|
||||
}
|
||||
$z.Dispose()
|
||||
if ($ok) { Write-Output ("xlsx 生成并通过自检: " + $Out + " (" + $rows.Count + " 行)") }
|
||||
Reference in New Issue
Block a user