mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-17 23:35:22 +03:00
feat(mxl-compile,mxl-decompile): columnStyles — оформление колонки
У ячейки есть style, у строки rowStyle, у колонки не было ничего — при том что
колонка ссылается в ту же палитру <format> и несёт те же свойства. В корпусе
ERP колонки используют шрифт (3006 форматов), выравнивание, рамки, скрытие и
прочее; всё это терялось при раундтрипе.
Колонка получает такой же именованный стиль: columnStyles рядом с columnWidths,
ключи той же грамматики диапазонов ("1", "2-8", "5,7,9"), значение — имя из
styles. Внутри columnSets тот же ключ. Формат колонки собирается из ширины и
свойств стиля: запись в палитре одна.
Шрифт по умолчанию колонке не навязываем — формат колонки без оформления это
ровно <width>, как пишет платформа.
Попутно два дефекта декомпилятора: стиль колонки не учитывался при отсечении
неиспользуемых стилей и пропадал целиком, а набор из одних неприметных свойств
(отступ, защита) получал зарезервированное имя default и тоже терялся.
На пилоте потери в категории colset[].col[].formatIndex упали с 86 до 39.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c9e490bd25
commit
4e389d0ef1
@@ -1,4 +1,4 @@
|
|||||||
# mxl-compile v1.29 — Compile 1C spreadsheet from JSON
|
# mxl-compile v1.30 — Compile 1C spreadsheet from JSON
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
@@ -382,6 +382,21 @@ function Build-ColWidthMap {
|
|||||||
|
|
||||||
$colWidthMap = Build-ColWidthMap $def.columnWidths
|
$colWidthMap = Build-ColWidthMap $def.columnWidths
|
||||||
|
|
||||||
|
# Стиль колонки — тот же именованный стиль, что у ячейки и строки: колонка третий владелец
|
||||||
|
# формата, и своих свойств у неё нет. Ключи те же, что у columnWidths.
|
||||||
|
function Build-ColStyleMap {
|
||||||
|
param($styles)
|
||||||
|
$map = @{}
|
||||||
|
if ($styles) {
|
||||||
|
foreach ($prop in $styles.PSObject.Properties) {
|
||||||
|
foreach ($c in (Parse-ColumnSpec $prop.Name)) { $map[$c] = "$($prop.Value)" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $map
|
||||||
|
}
|
||||||
|
|
||||||
|
$colStyleMap = Build-ColStyleMap $def.columnStyles
|
||||||
|
|
||||||
# Колоночные раскладки: документные columns/columnWidths — раскладка по умолчанию (в XML
|
# Колоночные раскладки: документные columns/columnWidths — раскладка по умолчанию (в XML
|
||||||
# элемент <columns> БЕЗ <id>, он всегда идёт первым). Дополнительные объявляются в
|
# элемент <columns> БЕЗ <id>, он всегда идёт первым). Дополнительные объявляются в
|
||||||
# columnSets, ключ — идентификатор, на него ссылается область ключом columnSet.
|
# columnSets, ключ — идентификатор, на него ссылается область ключом columnSet.
|
||||||
@@ -407,7 +422,7 @@ function ConvertTo-LayoutId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$columnLayouts = @()
|
$columnLayouts = @()
|
||||||
$columnLayouts += @{ Id = $null; Name = $null; Size = $totalColumns; Widths = $colWidthMap }
|
$columnLayouts += @{ Id = $null; Name = $null; Size = $totalColumns; Widths = $colWidthMap; Styles = $colStyleMap }
|
||||||
if ($def.columnSets) {
|
if ($def.columnSets) {
|
||||||
foreach ($prop in $def.columnSets.PSObject.Properties) {
|
foreach ($prop in $def.columnSets.PSObject.Properties) {
|
||||||
$cs = $prop.Value
|
$cs = $prop.Value
|
||||||
@@ -417,6 +432,7 @@ if ($def.columnSets) {
|
|||||||
Name = $prop.Name
|
Name = $prop.Name
|
||||||
Size = $size
|
Size = $size
|
||||||
Widths = Build-ColWidthMap $cs.columnWidths
|
Widths = Build-ColWidthMap $cs.columnWidths
|
||||||
|
Styles = Build-ColStyleMap $cs.columnStyles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,11 +471,12 @@ function Get-ColorNamespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Resolve-Style {
|
function Resolve-Style {
|
||||||
param([string]$styleName, [string]$fillType)
|
param([string]$styleName, [string]$fillType, [switch]$noDefaultFont)
|
||||||
|
|
||||||
# Набор свойств формата — «тег платформы → значение», только заданные. Порядок вставки
|
# Набор свойств формата — «тег платформы → значение», только заданные. Порядок вставки
|
||||||
# роли не играет: и ключ дедупликации, и эмиссия идут по каноническому порядку тегов.
|
# роли не играет: и ключ дедупликации, и эмиссия идут по каноническому порядку тегов.
|
||||||
$props = @{ font = $fontMap["default"] }
|
$props = @{}
|
||||||
|
if (-not $noDefaultFont) { $props['font'] = $fontMap["default"] }
|
||||||
|
|
||||||
if ($styleName -and $def.styles) {
|
if ($styleName -and $def.styles) {
|
||||||
$style = $def.styles.$styleName
|
$style = $def.styles.$styleName
|
||||||
@@ -677,12 +694,21 @@ function Register-Format {
|
|||||||
# 6a. Default width format
|
# 6a. Default width format
|
||||||
$defaultFormatIndex = Register-Format @{ width = $defaultWidth }
|
$defaultFormatIndex = Register-Format @{ width = $defaultWidth }
|
||||||
|
|
||||||
# 6b. Column width formats — по одной карте на каждую колоночную раскладку
|
# 6b. Column formats — по одной карте на каждую колоночную раскладку.
|
||||||
|
# У колонки бывает и ширина, и оформление: формат один, свойства складываются.
|
||||||
foreach ($layout in $columnLayouts) {
|
foreach ($layout in $columnLayouts) {
|
||||||
$map = @{} # 1-based col -> format index
|
$map = @{} # 1-based col -> format index
|
||||||
foreach ($col in ($layout.Widths.Keys | Sort-Object)) {
|
$cols = @($layout.Widths.Keys) + @($layout.Styles.Keys) | ForEach-Object { [int]$_ } |
|
||||||
$w = $layout.Widths[$col]
|
Select-Object -Unique | Sort-Object
|
||||||
$map[[int]$col] = Register-Format @{ width = $w }
|
foreach ($col in $cols) {
|
||||||
|
$props = @{}
|
||||||
|
if ($layout.Styles.ContainsKey($col)) {
|
||||||
|
# Шрифт по умолчанию колонке не навязываем: формат колонки без оформления —
|
||||||
|
# это ровно <width>, как пишет платформа.
|
||||||
|
$props = Resolve-Style -styleName $layout.Styles[$col] -fillType "" -noDefaultFont
|
||||||
|
}
|
||||||
|
if ($layout.Widths.ContainsKey($col)) { $props['width'] = $layout.Widths[$col] }
|
||||||
|
$map[$col] = Register-Format $props
|
||||||
}
|
}
|
||||||
$layout.FormatMap = $map
|
$layout.FormatMap = $map
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# mxl-compile v1.29 — Compile 1C spreadsheet from JSON
|
# mxl-compile v1.30 — Compile 1C spreadsheet from JSON
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
import argparse
|
import argparse
|
||||||
import hashlib
|
import hashlib
|
||||||
@@ -595,6 +595,18 @@ def main():
|
|||||||
|
|
||||||
col_width_map = build_col_width_map(defn.get('columnWidths'))
|
col_width_map = build_col_width_map(defn.get('columnWidths'))
|
||||||
|
|
||||||
|
# Стиль колонки — тот же именованный стиль, что у ячейки и строки: колонка третий
|
||||||
|
# владелец формата, и своих свойств у неё нет. Ключи те же, что у columnWidths.
|
||||||
|
def build_col_style_map(styles):
|
||||||
|
out = {}
|
||||||
|
if styles:
|
||||||
|
for prop_name, prop_value in styles.items():
|
||||||
|
for c in parse_column_spec(prop_name):
|
||||||
|
out[c] = str(prop_value)
|
||||||
|
return out
|
||||||
|
|
||||||
|
col_style_map = build_col_style_map(defn.get('columnStyles'))
|
||||||
|
|
||||||
# Колоночные раскладки: документные columns/columnWidths — раскладка по умолчанию (в XML
|
# Колоночные раскладки: документные columns/columnWidths — раскладка по умолчанию (в XML
|
||||||
# элемент <columns> БЕЗ <id>, он всегда идёт первым). Дополнительные объявляются в
|
# элемент <columns> БЕЗ <id>, он всегда идёт первым). Дополнительные объявляются в
|
||||||
# columnSets, ключ — идентификатор, на него ссылается область ключом columnSet.
|
# columnSets, ключ — идентификатор, на него ссылается область ключом columnSet.
|
||||||
@@ -616,7 +628,8 @@ def main():
|
|||||||
h = b.hex()
|
h = b.hex()
|
||||||
return f'{h[0:8]}-{h[8:12]}-{h[12:16]}-{h[16:20]}-{h[20:32]}'
|
return f'{h[0:8]}-{h[8:12]}-{h[12:16]}-{h[16:20]}-{h[20:32]}'
|
||||||
|
|
||||||
column_layouts = [{'Id': None, 'Name': None, 'Size': total_columns, 'Widths': col_width_map}]
|
column_layouts = [{'Id': None, 'Name': None, 'Size': total_columns,
|
||||||
|
'Widths': col_width_map, 'Styles': col_style_map}]
|
||||||
for set_name, cs in (defn.get('columnSets') or {}).items():
|
for set_name, cs in (defn.get('columnSets') or {}).items():
|
||||||
size = int(cs['columns']) if cs.get('columns') is not None else total_columns
|
size = int(cs['columns']) if cs.get('columns') is not None else total_columns
|
||||||
column_layouts.append({
|
column_layouts.append({
|
||||||
@@ -624,6 +637,7 @@ def main():
|
|||||||
'Name': set_name,
|
'Name': set_name,
|
||||||
'Size': size,
|
'Size': size,
|
||||||
'Widths': build_col_width_map(cs.get('columnWidths')),
|
'Widths': build_col_width_map(cs.get('columnWidths')),
|
||||||
|
'Styles': build_col_style_map(cs.get('columnStyles')),
|
||||||
})
|
})
|
||||||
|
|
||||||
# --- 5. Style resolver ---
|
# --- 5. Style resolver ---
|
||||||
@@ -651,10 +665,10 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
return {'Style': canon, 'Width': width, 'Gap': gap}
|
return {'Style': canon, 'Width': width, 'Gap': gap}
|
||||||
|
|
||||||
def resolve_style(style_name, fill_type):
|
def resolve_style(style_name, fill_type, no_default_font=False):
|
||||||
# Набор свойств формата — «тег платформы → значение», только заданные. Порядок вставки
|
# Набор свойств формата — «тег платформы → значение», только заданные. Порядок вставки
|
||||||
# роли не играет: и ключ дедупликации, и эмиссия идут по каноническому порядку тегов.
|
# роли не играет: и ключ дедупликации, и эмиссия идут по каноническому порядку тегов.
|
||||||
props = {'font': font_map.get('default', 0)}
|
props = {} if no_default_font else {'font': font_map.get('default', 0)}
|
||||||
|
|
||||||
if style_name and defn.get('styles'):
|
if style_name and defn.get('styles'):
|
||||||
style = defn['styles'].get(style_name)
|
style = defn['styles'].get(style_name)
|
||||||
@@ -759,12 +773,19 @@ def main():
|
|||||||
# 6a. Default width format
|
# 6a. Default width format
|
||||||
default_format_index = register_format({'width': default_width})
|
default_format_index = register_format({'width': default_width})
|
||||||
|
|
||||||
# 6b. Column width formats — по одной карте на каждую колоночную раскладку
|
# 6b. Column formats — по одной карте на каждую колоночную раскладку.
|
||||||
|
# У колонки бывает и ширина, и оформление: формат один, свойства складываются.
|
||||||
for layout in column_layouts:
|
for layout in column_layouts:
|
||||||
fmap = {} # 1-based col -> format index
|
fmap = {} # 1-based col -> format index
|
||||||
for col in sorted(layout['Widths']):
|
for col in sorted({int(c) for c in list(layout['Widths']) + list(layout['Styles'])}):
|
||||||
w = layout['Widths'][col]
|
props = {}
|
||||||
fmap[int(col)] = register_format({'width': w})
|
if col in layout['Styles']:
|
||||||
|
# Шрифт по умолчанию колонке не навязываем: формат колонки без оформления —
|
||||||
|
# это ровно <width>, как пишет платформа.
|
||||||
|
props = resolve_style(layout['Styles'][col], '', no_default_font=True)
|
||||||
|
if col in layout['Widths']:
|
||||||
|
props['width'] = layout['Widths'][col]
|
||||||
|
fmap[col] = register_format(props)
|
||||||
layout['FormatMap'] = fmap
|
layout['FormatMap'] = fmap
|
||||||
col_format_map = column_layouts[0]['FormatMap']
|
col_format_map = column_layouts[0]['FormatMap']
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# mxl-decompile v1.10 — Decompile 1C spreadsheet to JSON
|
# mxl-decompile v1.11 — Decompile 1C spreadsheet to JSON
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
@@ -191,12 +191,17 @@ function Read-ColumnSet {
|
|||||||
$widths.Add([string]($col0 + 1), $fmt.Width)
|
$widths.Add([string]($col0 + 1), $fmt.Width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# Формат колонки несёт не только ширину — имя стиля подставим ниже, когда стили
|
||||||
|
# будут поименованы.
|
||||||
|
$fmtIdx = [ordered]@{}
|
||||||
|
foreach ($col0 in ($byIdx.Keys | Sort-Object)) { $fmtIdx.Add([string]($col0 + 1), $byIdx[$col0]) }
|
||||||
$sizeNode = $node.SelectSingleNode("d:size", $ns)
|
$sizeNode = $node.SelectSingleNode("d:size", $ns)
|
||||||
$idNode = $node.SelectSingleNode("d:id", $ns)
|
$idNode = $node.SelectSingleNode("d:id", $ns)
|
||||||
return @{
|
return @{
|
||||||
Id = if ($idNode) { $idNode.InnerText } else { $null }
|
Id = if ($idNode) { $idNode.InnerText } else { $null }
|
||||||
Size = if ($sizeNode) { [int]$sizeNode.InnerText } else { 0 }
|
Size = if ($sizeNode) { [int]$sizeNode.InnerText } else { 0 }
|
||||||
Widths = $widths
|
Widths = $widths
|
||||||
|
FmtIdx = $fmtIdx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,6 +499,18 @@ foreach ($r in $rowData.Values) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Колонка — третий владелец формата, её оформление тоже становится именованным стилем.
|
||||||
|
foreach ($cs in $columnSets) {
|
||||||
|
foreach ($fi in $cs.FmtIdx.Values) {
|
||||||
|
$fmt = Get-Format $fi
|
||||||
|
if (-not $fmt) { continue }
|
||||||
|
if ((Get-StyleProps $fmt).Count -eq 0) { continue }
|
||||||
|
$key = Get-StyleKey $fmt
|
||||||
|
if (-not $styleKeys.Contains($key)) { $styleKeys[$key] = $fmt }
|
||||||
|
$formatToStyleKey[$fi] = $key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Имя стиля — читаемая метка по самым заметным свойствам. Полнота тут не нужна:
|
# Имя стиля — читаемая метка по самым заметным свойствам. Полнота тут не нужна:
|
||||||
# различает стили ключ, имя лишь помогает автору ориентироваться.
|
# различает стили ключ, имя лишь помогает автору ориентироваться.
|
||||||
function Name-Style {
|
function Name-Style {
|
||||||
@@ -525,7 +542,10 @@ function Name-Style {
|
|||||||
if ($props.Contains('backColor')) { $parts += "bg" }
|
if ($props.Contains('backColor')) { $parts += "bg" }
|
||||||
if ($props.Contains('format')) { $parts += "fmt" }
|
if ($props.Contains('format')) { $parts += "fmt" }
|
||||||
|
|
||||||
if ($parts.Count -eq 0) { return "default" }
|
# Имя "default" зарезервировано за стилем БЕЗ свойств: под ним компилятор понимает
|
||||||
|
# отсутствие оформления. Набор из одних неприметных свойств (отступ, защита) обязан
|
||||||
|
# получить своё имя, иначе он потеряется.
|
||||||
|
if ($parts.Count -eq 0) { return $(if ($props.Count -eq 0) { "default" } else { "style" }) }
|
||||||
return ($parts -join "-")
|
return ($parts -join "-")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,6 +579,18 @@ function Get-StyleName {
|
|||||||
return "default"
|
return "default"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Колонки раскладки, у которых формат несёт не только ширину, — «колонка → стиль».
|
||||||
|
function Get-ColumnStyles {
|
||||||
|
param($cs)
|
||||||
|
$out = [ordered]@{}
|
||||||
|
foreach ($col in $cs.FmtIdx.Keys) {
|
||||||
|
$fi = $cs.FmtIdx[$col]
|
||||||
|
$fmt = Get-Format $fi
|
||||||
|
if ($fmt -and (Get-StyleProps $fmt).Count -gt 0) { $out[$col] = Get-StyleName $fi }
|
||||||
|
}
|
||||||
|
return $out
|
||||||
|
}
|
||||||
|
|
||||||
# Список признаётся позиционным по тому же правилу, что и в компиляторе: есть элемент-строка
|
# Список признаётся позиционным по тому же правилу, что и в компиляторе: есть элемент-строка
|
||||||
# или пропуск. Список из одних объектов таковым не считаем — он читается как обычный.
|
# или пропуск. Список из одних объектов таковым не считаем — он читается как обычный.
|
||||||
function Test-PositionalList {
|
function Test-PositionalList {
|
||||||
@@ -880,6 +912,10 @@ $result = [ordered]@{
|
|||||||
defaultWidth = $defaultWidth
|
defaultWidth = $defaultWidth
|
||||||
}
|
}
|
||||||
if ($compressedWidths.Count -gt 0) { $result["columnWidths"] = $compressedWidths }
|
if ($compressedWidths.Count -gt 0) { $result["columnWidths"] = $compressedWidths }
|
||||||
|
if ($defaultSet) {
|
||||||
|
$defaultColStyles = Get-ColumnStyles $defaultSet
|
||||||
|
if ($defaultColStyles.Count -gt 0) { $result["columnStyles"] = $defaultColStyles }
|
||||||
|
}
|
||||||
# Набор языков объявляем, только если он отличается от умолчания компилятора (один ru).
|
# Набор языков объявляем, только если он отличается от умолчания компилятора (один ru).
|
||||||
if ($textLanguages.Count -gt 0 -and -not ($textLanguages.Count -eq 1 -and $textLanguages[0] -ceq 'ru')) {
|
if ($textLanguages.Count -gt 0 -and -not ($textLanguages.Count -eq 1 -and $textLanguages[0] -ceq 'ru')) {
|
||||||
$result["textLanguages"] = [array]$textLanguages
|
$result["textLanguages"] = [array]$textLanguages
|
||||||
@@ -900,6 +936,10 @@ foreach ($a in $dslAreas) {
|
|||||||
if ($cellList) { foreach ($c in $cellList) { if ($c -isnot [string] -and $c.style) { $usedStyles[$c.style] = $true } } }
|
if ($cellList) { foreach ($c in $cellList) { if ($c -isnot [string] -and $c.style) { $usedStyles[$c.style] = $true } } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# Стиль бывает не только у ячейки и строки: колонка — третий владелец формата.
|
||||||
|
foreach ($cs in $columnSets) {
|
||||||
|
foreach ($name in (Get-ColumnStyles $cs).Values) { $usedStyles[$name] = $true }
|
||||||
|
}
|
||||||
$toRemove = @($styleDefs.Keys | Where-Object { -not $usedStyles.ContainsKey($_) })
|
$toRemove = @($styleDefs.Keys | Where-Object { -not $usedStyles.ContainsKey($_) })
|
||||||
foreach ($s in $toRemove) { $styleDefs.Remove($s)
|
foreach ($s in $toRemove) { $styleDefs.Remove($s)
|
||||||
}
|
}
|
||||||
@@ -916,6 +956,8 @@ if ($extraSets.Count -gt 0) {
|
|||||||
foreach ($cs in $extraSets) {
|
foreach ($cs in $extraSets) {
|
||||||
$entry = [ordered]@{ columns = $cs.Size }
|
$entry = [ordered]@{ columns = $cs.Size }
|
||||||
if ($cs.Widths.Count -gt 0) { $entry["columnWidths"] = $cs.Widths }
|
if ($cs.Widths.Count -gt 0) { $entry["columnWidths"] = $cs.Widths }
|
||||||
|
$csStyles = Get-ColumnStyles $cs
|
||||||
|
if ($csStyles.Count -gt 0) { $entry["columnStyles"] = $csStyles }
|
||||||
$setsOut[$cs.Id] = $entry
|
$setsOut[$cs.Id] = $entry
|
||||||
}
|
}
|
||||||
$result["columnSets"] = $setsOut
|
$result["columnSets"] = $setsOut
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# mxl-decompile v1.10 — Decompile 1C spreadsheet to JSON
|
# mxl-decompile v1.11 — Decompile 1C spreadsheet to JSON
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -363,6 +363,9 @@ def main():
|
|||||||
"Id": (text_of(id_node) or None) if id_node is not None else None,
|
"Id": (text_of(id_node) or None) if id_node is not None else None,
|
||||||
"Size": int_of(size_node) if size_node is not None else 0,
|
"Size": int_of(size_node) if size_node is not None else 0,
|
||||||
"Widths": widths,
|
"Widths": widths,
|
||||||
|
# Формат колонки несёт не только ширину — имя стиля подставим ниже, когда стили
|
||||||
|
# будут поименованы.
|
||||||
|
"FmtIdx": {str(c0 + 1): by_idx[c0] for c0 in sorted(by_idx.keys())},
|
||||||
}
|
}
|
||||||
|
|
||||||
column_sets = [read_column_set(cn) for cn in findall(root, "d:columns")]
|
column_sets = [read_column_set(cn) for cn in findall(root, "d:columns")]
|
||||||
@@ -656,6 +659,17 @@ def main():
|
|||||||
style_keys[key] = fmt
|
style_keys[key] = fmt
|
||||||
format_to_style_key[cell["FormatIdx"]] = key
|
format_to_style_key[cell["FormatIdx"]] = key
|
||||||
|
|
||||||
|
# Колонка — третий владелец формата, её оформление тоже становится именованным стилем.
|
||||||
|
for cs in column_sets:
|
||||||
|
for fi in cs["FmtIdx"].values():
|
||||||
|
fmt = get_format(fi)
|
||||||
|
if not fmt or not style_props(fmt):
|
||||||
|
continue
|
||||||
|
key = get_style_key(fmt)
|
||||||
|
if key not in style_keys:
|
||||||
|
style_keys[key] = fmt
|
||||||
|
format_to_style_key[fi] = key
|
||||||
|
|
||||||
def name_style(fmt):
|
def name_style(fmt):
|
||||||
"""Имя стиля — читаемая метка по самым заметным свойствам. Полнота тут не нужна:
|
"""Имя стиля — читаемая метка по самым заметным свойствам. Полнота тут не нужна:
|
||||||
различает стили ключ, имя лишь помогает автору ориентироваться."""
|
различает стили ключ, имя лишь помогает автору ориентироваться."""
|
||||||
@@ -694,7 +708,10 @@ def main():
|
|||||||
parts.append("fmt")
|
parts.append("fmt")
|
||||||
|
|
||||||
if len(parts) == 0:
|
if len(parts) == 0:
|
||||||
return "default"
|
# Имя "default" зарезервировано за стилем БЕЗ свойств: под ним компилятор
|
||||||
|
# понимает отсутствие оформления. Набор из одних неприметных свойств
|
||||||
|
# (отступ, защита) обязан получить своё имя, иначе он потеряется.
|
||||||
|
return "default" if not props else "style"
|
||||||
return "-".join(parts)
|
return "-".join(parts)
|
||||||
|
|
||||||
style_names = OrderedDict()
|
style_names = OrderedDict()
|
||||||
@@ -726,6 +743,15 @@ def main():
|
|||||||
return style_names[key]
|
return style_names[key]
|
||||||
return "default"
|
return "default"
|
||||||
|
|
||||||
|
def column_styles_of(cs):
|
||||||
|
"""Колонки раскладки, у которых формат несёт не только ширину, — «колонка → стиль»."""
|
||||||
|
out = OrderedDict()
|
||||||
|
for col, fi in cs["FmtIdx"].items():
|
||||||
|
fmt = get_format(fi)
|
||||||
|
if fmt and style_props(fmt):
|
||||||
|
out[col] = get_style_name(fi)
|
||||||
|
return out
|
||||||
|
|
||||||
def to_positional_cells(cells):
|
def to_positional_cells(cells):
|
||||||
"""Позиционная запись списка ячеек: позиция берётся из порядка, `col` не пишется.
|
"""Позиционная запись списка ячеек: позиция берётся из порядка, `col` не пишется.
|
||||||
Применяем, когда первая ячейка стоит в колонке 1 — иначе список начнётся с череды None
|
Применяем, когда первая ячейка стоит в колонке 1 — иначе список начнётся с череды None
|
||||||
@@ -1022,6 +1048,10 @@ def main():
|
|||||||
result["defaultWidth"] = default_width
|
result["defaultWidth"] = default_width
|
||||||
if len(compressed_widths) > 0:
|
if len(compressed_widths) > 0:
|
||||||
result["columnWidths"] = compressed_widths
|
result["columnWidths"] = compressed_widths
|
||||||
|
if default_set:
|
||||||
|
default_col_styles = column_styles_of(default_set)
|
||||||
|
if default_col_styles:
|
||||||
|
result["columnStyles"] = default_col_styles
|
||||||
# Набор языков объявляем, только если он отличается от умолчания компилятора (один ru).
|
# Набор языков объявляем, только если он отличается от умолчания компилятора (один ru).
|
||||||
if text_languages and text_languages != ['ru']:
|
if text_languages and text_languages != ['ru']:
|
||||||
result["textLanguages"] = text_languages
|
result["textLanguages"] = text_languages
|
||||||
@@ -1047,6 +1077,11 @@ def main():
|
|||||||
for c in cell_list:
|
for c in cell_list:
|
||||||
if isinstance(c, dict) and "style" in c:
|
if isinstance(c, dict) and "style" in c:
|
||||||
used_styles.add(c["style"])
|
used_styles.add(c["style"])
|
||||||
|
# Стиль бывает не только у ячейки и строки: колонка — третий владелец формата.
|
||||||
|
for src in [result.get("columnStyles")] + [
|
||||||
|
(cs or {}).get("columnStyles") for cs in (result.get("columnSets") or {}).values()]:
|
||||||
|
for name in (src or {}).values():
|
||||||
|
used_styles.add(name)
|
||||||
to_remove = [s for s in style_defs if s not in used_styles]
|
to_remove = [s for s in style_defs if s not in used_styles]
|
||||||
for s in to_remove:
|
for s in to_remove:
|
||||||
del style_defs[s]
|
del style_defs[s]
|
||||||
@@ -1064,6 +1099,9 @@ def main():
|
|||||||
entry = OrderedDict([("columns", cs["Size"])])
|
entry = OrderedDict([("columns", cs["Size"])])
|
||||||
if cs["Widths"]:
|
if cs["Widths"]:
|
||||||
entry["columnWidths"] = cs["Widths"]
|
entry["columnWidths"] = cs["Widths"]
|
||||||
|
styles_out = column_styles_of(cs)
|
||||||
|
if styles_out:
|
||||||
|
entry["columnStyles"] = styles_out
|
||||||
sets_out[cs["Id"]] = entry
|
sets_out[cs["Id"]] = entry
|
||||||
result["columnSets"] = sets_out
|
result["columnSets"] = sets_out
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "Стиль колонки — в документной раскладке и в columnSets",
|
||||||
|
"input": {
|
||||||
|
"columns": 5,
|
||||||
|
"defaultWidth": 20,
|
||||||
|
"fonts": {
|
||||||
|
"default": { "face": "Arial", "size": 10 },
|
||||||
|
"bold": { "face": "Arial", "size": 10, "bold": true }
|
||||||
|
},
|
||||||
|
"styles": {
|
||||||
|
"по-центру": { "horizontalAlignment": "Center" },
|
||||||
|
"скрытая": { "hidden": true },
|
||||||
|
"жирная-с-фоном": { "font": "bold", "backColor": "#EBEBEB" }
|
||||||
|
},
|
||||||
|
"columnWidths": { "1": 30, "2-3": 15 },
|
||||||
|
"columnStyles": { "1": "по-центру", "4": "скрытая" },
|
||||||
|
"columnSets": {
|
||||||
|
"таблица": {
|
||||||
|
"columns": 3,
|
||||||
|
"columnWidths": { "1": 12 },
|
||||||
|
"columnStyles": { "2-3": "жирная-с-фоном" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"areas": [
|
||||||
|
{
|
||||||
|
"name": "Шапка",
|
||||||
|
"rows": [
|
||||||
|
{ "cells": [ { "col": 1, "span": 5, "text": "Заголовок" } ] }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Таблица",
|
||||||
|
"columnSet": "таблица",
|
||||||
|
"rows": [
|
||||||
|
{ "cells": [
|
||||||
|
{ "col": 1, "param": "Код" },
|
||||||
|
{ "col": 2, "param": "Имя" },
|
||||||
|
{ "col": 3, "param": "Сумма" }
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": { "outputPath": "Template.xml" },
|
||||||
|
"validatePath": "Template.xml",
|
||||||
|
"expect": { "files": ["Template.xml"] }
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document xmlns="http://v8.1c.ru/8.2/data/spreadsheet" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<languageSettings>
|
||||||
|
<currentLanguage>ru</currentLanguage>
|
||||||
|
<defaultLanguage>ru</defaultLanguage>
|
||||||
|
<languageInfo>
|
||||||
|
<id>ru</id>
|
||||||
|
<code>Русский</code>
|
||||||
|
<description>Русский</description>
|
||||||
|
</languageInfo>
|
||||||
|
</languageSettings>
|
||||||
|
<columns>
|
||||||
|
<size>5</size>
|
||||||
|
<columnsItem>
|
||||||
|
<index>0</index>
|
||||||
|
<column>
|
||||||
|
<formatIndex>2</formatIndex>
|
||||||
|
</column>
|
||||||
|
</columnsItem>
|
||||||
|
<columnsItem>
|
||||||
|
<index>1</index>
|
||||||
|
<column>
|
||||||
|
<formatIndex>3</formatIndex>
|
||||||
|
</column>
|
||||||
|
</columnsItem>
|
||||||
|
<columnsItem>
|
||||||
|
<index>2</index>
|
||||||
|
<column>
|
||||||
|
<formatIndex>3</formatIndex>
|
||||||
|
</column>
|
||||||
|
</columnsItem>
|
||||||
|
<columnsItem>
|
||||||
|
<index>3</index>
|
||||||
|
<column>
|
||||||
|
<formatIndex>4</formatIndex>
|
||||||
|
</column>
|
||||||
|
</columnsItem>
|
||||||
|
</columns>
|
||||||
|
<columns>
|
||||||
|
<id>01f06d2d-2103-3169-8cc8-32872f100129</id>
|
||||||
|
<size>3</size>
|
||||||
|
<columnsItem>
|
||||||
|
<index>0</index>
|
||||||
|
<column>
|
||||||
|
<formatIndex>5</formatIndex>
|
||||||
|
</column>
|
||||||
|
</columnsItem>
|
||||||
|
<columnsItem>
|
||||||
|
<index>1</index>
|
||||||
|
<column>
|
||||||
|
<formatIndex>6</formatIndex>
|
||||||
|
</column>
|
||||||
|
</columnsItem>
|
||||||
|
<columnsItem>
|
||||||
|
<index>2</index>
|
||||||
|
<column>
|
||||||
|
<formatIndex>6</formatIndex>
|
||||||
|
</column>
|
||||||
|
</columnsItem>
|
||||||
|
</columns>
|
||||||
|
<rowsItem>
|
||||||
|
<index>0</index>
|
||||||
|
<row>
|
||||||
|
<c>
|
||||||
|
<c>
|
||||||
|
<f>1</f>
|
||||||
|
<tl>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>Заголовок</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</tl>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
</row>
|
||||||
|
</rowsItem>
|
||||||
|
<rowsItem>
|
||||||
|
<index>1</index>
|
||||||
|
<row>
|
||||||
|
<columnsID>01f06d2d-2103-3169-8cc8-32872f100129</columnsID>
|
||||||
|
<c>
|
||||||
|
<c>
|
||||||
|
<f>7</f>
|
||||||
|
<parameter>Код</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<c>
|
||||||
|
<f>7</f>
|
||||||
|
<parameter>Имя</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
<c>
|
||||||
|
<c>
|
||||||
|
<f>7</f>
|
||||||
|
<parameter>Сумма</parameter>
|
||||||
|
</c>
|
||||||
|
</c>
|
||||||
|
</row>
|
||||||
|
</rowsItem>
|
||||||
|
<templateMode>true</templateMode>
|
||||||
|
<defaultFormatIndex>1</defaultFormatIndex>
|
||||||
|
<height>2</height>
|
||||||
|
<vgRows>2</vgRows>
|
||||||
|
<merge>
|
||||||
|
<r>0</r>
|
||||||
|
<c>0</c>
|
||||||
|
<w>4</w>
|
||||||
|
</merge>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Таблица</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>1</beginRow>
|
||||||
|
<endRow>1</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
|
<namedItem xsi:type="NamedItemCells">
|
||||||
|
<name>Шапка</name>
|
||||||
|
<area>
|
||||||
|
<type>Rows</type>
|
||||||
|
<beginRow>0</beginRow>
|
||||||
|
<endRow>0</endRow>
|
||||||
|
<beginColumn>-1</beginColumn>
|
||||||
|
<endColumn>-1</endColumn>
|
||||||
|
</area>
|
||||||
|
</namedItem>
|
||||||
|
<font faceName="Arial" height="10" bold="false" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
||||||
|
<font faceName="Arial" height="10" bold="true" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
||||||
|
<format>
|
||||||
|
<width>20</width>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<width>30</width>
|
||||||
|
<horizontalAlignment>Center</horizontalAlignment>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<width>15</width>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<hidden>true</hidden>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<width>12</width>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<font>1</font>
|
||||||
|
<backColor>#EBEBEB</backColor>
|
||||||
|
</format>
|
||||||
|
<format>
|
||||||
|
<font>0</font>
|
||||||
|
<fillType>Parameter</fillType>
|
||||||
|
</format>
|
||||||
|
</document>
|
||||||
Reference in New Issue
Block a user