mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-13 06:53:21 +03:00
feat(mxl-compile): стиль умеет все свойства формата, а не семь
Стиль описывал 7 свойств из 47, которые платформа хранит в <format>. Не было
самого частого тега корпуса — backColor (1.7 млн вхождений), а также textColor,
textPlacement, protection, hidden, indent, borderColor, textOrientation и хвоста.
Теперь ключ стиля — имя тега платформы, без исключений: помнить, какие ключи
названы по-своему, больше не нужно. Прежние align/valign/wrap продолжают
работать молча, как синонимы; там же CSS-имена (background, color,
border-bottom) и русские имена свойств. Таблицы типов значений и допустимых
значений перечислений сняты с корпуса, а не выписаны на глаз.
Рамка: пять плоских ключей (border и четыре стороны) со значением
{ style, width } либо строкой стиля; линия регистрируется в палитре <line>,
которая раньше знала только «тонкую» и «толстую» Solid. Четыре одинаковые
стороны сворачиваются в один <border> — правило проверено на корпусе:
70 265 свёрнутых форматов против 36 783 записанных по сторонам, и среди
вторых нет ни одного с четырьмя совпадающими значениями.
Цвет — нотация самой платформы: #RRGGBB, style:Имя, web:Имя, win:Имя. Первые
две пишутся дословно (префикс style объявлен в корне документа), для web и win
платформа дописывает объявление xmlns прямо на узел — делаем так же.
containsValue / valueType / controlType намеренно не заведены: это свойства
конкретной ячейки, а стиль — сущность общая, один на многие ячейки.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c559696c5a
commit
d3c16f56c5
@@ -1,4 +1,4 @@
|
||||
# mxl-compile v1.28 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.29 — Compile 1C spreadsheet from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -268,33 +268,29 @@ if (-not $hasDefault) {
|
||||
Add-Font -name "default" -fontDef $defaultDef
|
||||
}
|
||||
|
||||
# --- 3. Determine line palette ---
|
||||
# --- 3. Line palette ---
|
||||
# Рамка хранится не в формате, а в палитре <line>: формат ссылается на запись индексом.
|
||||
# Запись — тройка (стиль, ширина, gap); в корпусе gap всегда false, но тег платформа пишет.
|
||||
$script:lineRegistry = @()
|
||||
|
||||
$hasThinBorders = $false
|
||||
$hasThickBorders = $false
|
||||
function Get-LineKey {
|
||||
param($ln)
|
||||
return "$($ln.Style)|$($ln.Width)|$($ln.Gap)"
|
||||
}
|
||||
|
||||
# Scan styles for border usage
|
||||
if ($def.styles) {
|
||||
foreach ($prop in $def.styles.PSObject.Properties) {
|
||||
$s = $prop.Value
|
||||
if ($s.border -and $s.border -ne "none") {
|
||||
if ($s.borderWidth -eq "thick") {
|
||||
$hasThickBorders = $true
|
||||
} else {
|
||||
$hasThinBorders = $true
|
||||
}
|
||||
}
|
||||
function Register-Line {
|
||||
param($ln)
|
||||
$key = Get-LineKey $ln
|
||||
for ($i = 0; $i -lt $script:lineRegistry.Count; $i++) {
|
||||
if ((Get-LineKey $script:lineRegistry[$i]) -ceq $key) { return $i }
|
||||
}
|
||||
$script:lineRegistry += $ln
|
||||
return $script:lineRegistry.Count - 1
|
||||
}
|
||||
|
||||
$thinLineIndex = -1
|
||||
$thickLineIndex = -1
|
||||
$lineCount = 0
|
||||
if ($hasThinBorders) {
|
||||
$thinLineIndex = $lineCount; $lineCount++
|
||||
}
|
||||
if ($hasThickBorders) {
|
||||
$thickLineIndex = $lineCount; $lineCount++
|
||||
function Get-LineStyles {
|
||||
# Стили линии, встречающиеся в палитрах корпуса.
|
||||
return @('Solid', 'None', 'Dotted', 'ThinDashed', 'LargeDashed', 'ThickDashed', 'Double')
|
||||
}
|
||||
|
||||
# --- 4. Parse column width specs ---
|
||||
@@ -427,71 +423,131 @@ if ($def.columnSets) {
|
||||
|
||||
# --- 5. Style resolver ---
|
||||
|
||||
# Значение рамки: строка стиля ("Dotted") либо объект { style, width, gap }.
|
||||
# Прежняя запись borderWidth: thin/thick — это ширина 1 и 2.
|
||||
function ConvertTo-LineValue {
|
||||
param($val, [string]$where)
|
||||
$style = 'Solid'; $width = 1; $gap = 'false'
|
||||
if ($val -is [string] -or $val -is [int]) {
|
||||
$style = "$val"
|
||||
} else {
|
||||
if ($null -ne $val.style) { $style = "$($val.style)" }
|
||||
if ($null -ne $val.width) { $width = "$($val.width)" }
|
||||
if ($null -ne $val.gap) { $gap = if ($val.gap -eq $true) { 'true' } else { 'false' } }
|
||||
}
|
||||
if ($style -ceq 'thin') { $style = 'Solid'; $width = 1 }
|
||||
elseif ($style -ceq 'thick') { $style = 'Solid'; $width = 2 }
|
||||
$canon = Get-LineStyles | Where-Object { $_ -eq $style } | Select-Object -First 1
|
||||
if (-not $canon) {
|
||||
[Console]::Error.WriteLine("Unknown border style `"$style`" ($where). Allowed: $((Get-LineStyles) -join ', ')")
|
||||
exit 1
|
||||
}
|
||||
return @{ Style = $canon; Width = $width; Gap = $gap }
|
||||
}
|
||||
|
||||
# Цвет — значение с префиксом пространства имён (нотация платформы). style: объявлен в корне
|
||||
# документа, web/win — нет, поэтому платформа дописывает объявление прямо на узел.
|
||||
function Get-ColorNamespace {
|
||||
param([string]$val)
|
||||
if ($val -like 'web:*') { return 'http://v8.1c.ru/8.1/data/ui/colors/web' }
|
||||
if ($val -like 'win:*') { return 'http://v8.1c.ru/8.1/data/ui/colors/windows' }
|
||||
return ''
|
||||
}
|
||||
|
||||
function Resolve-Style {
|
||||
param([string]$styleName, [string]$fillType)
|
||||
|
||||
$fontIdx = $fontMap["default"]
|
||||
$lb = -1; $tb = -1; $rb = -1; $bb = -1
|
||||
$ha = ""; $va = ""; $nf = ""
|
||||
$wrap = $false
|
||||
# Набор свойств формата — «тег платформы → значение», только заданные. Порядок вставки
|
||||
# роли не играет: и ключ дедупликации, и эмиссия идут по каноническому порядку тегов.
|
||||
$props = @{ font = $fontMap["default"] }
|
||||
|
||||
if ($styleName -and $def.styles) {
|
||||
$style = $def.styles.$styleName
|
||||
if ($style) {
|
||||
# Font
|
||||
if ($style.font -and $fontMap.Contains($style.font)) {
|
||||
$fontIdx = $fontMap[$style.font]
|
||||
}
|
||||
$kinds = Get-FormatTagKind
|
||||
$enums = Get-FormatEnumValues
|
||||
$synonyms = Get-StyleKeySynonyms
|
||||
$where = "style `"$styleName`""
|
||||
|
||||
# Borders
|
||||
if ($style.border -and $style.border -ne "none") {
|
||||
$lineIdx = if ($style.borderWidth -eq "thick") { $thickLineIndex } else { $thinLineIndex }
|
||||
foreach ($side in ($style.border -split ',')) {
|
||||
switch ($side.Trim()) {
|
||||
"all" { $lb = $lineIdx; $tb = $lineIdx; $rb = $lineIdx; $bb = $lineIdx }
|
||||
"left" { $lb = $lineIdx }
|
||||
"top" { $tb = $lineIdx }
|
||||
"right" { $rb = $lineIdx }
|
||||
"bottom" { $bb = $lineIdx }
|
||||
# Прежняя запись рамки: стороны строкой + borderWidth. Разворачиваем в посторонние
|
||||
# ключи ДО общего разбора, чтобы дальше был один путь.
|
||||
$sideKeys = @{ left = 'leftBorder'; top = 'topBorder'; right = 'rightBorder'; bottom = 'bottomBorder' }
|
||||
$legacyBorder = $style.border
|
||||
if ($legacyBorder -is [string] -and $legacyBorder -and (Get-LineStyles | Where-Object { $_ -eq $legacyBorder }).Count -eq 0) {
|
||||
$ln = ConvertTo-LineValue @{ style = 'Solid'; width = $(if ("$($style.borderWidth)" -ceq 'thick') { 2 } else { 1 }) } $where
|
||||
$idx = Register-Line $ln
|
||||
foreach ($side in ($legacyBorder -split ',')) {
|
||||
$s = $side.Trim().ToLower()
|
||||
if ($s -eq 'none') { continue }
|
||||
if ($s -eq 'all') {
|
||||
foreach ($k in $sideKeys.Values) { $props[$k] = $idx }
|
||||
} elseif ($sideKeys.ContainsKey($s)) {
|
||||
$props[$sideKeys[$s]] = $idx
|
||||
} else {
|
||||
[Console]::Error.WriteLine("Unknown border side `"$($side.Trim())`" ($where). Allowed: all, left, top, right, bottom, none")
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Alignment
|
||||
if ($style.align) {
|
||||
switch ($style.align) {
|
||||
"left" { $ha = "Left" }
|
||||
"center" { $ha = "Center" }
|
||||
"right" { $ha = "Right" }
|
||||
foreach ($p in $style.PSObject.Properties) {
|
||||
$raw = $p.Name
|
||||
# Синонимы: канон побеждает, сравнение без регистра и пробелов.
|
||||
$norm = ($raw -replace '\s', '').ToLower()
|
||||
$tag = if ($synonyms.ContainsKey($norm)) { $synonyms[$norm] } else { $raw }
|
||||
if ($tag -ceq 'borderWidth') { continue }
|
||||
if ($tag -ceq 'border' -and $legacyBorder -is [string] -and
|
||||
(Get-LineStyles | Where-Object { $_ -eq $legacyBorder }).Count -eq 0) { continue }
|
||||
|
||||
$val = $p.Value
|
||||
if ($null -eq $val -or ($val -is [string] -and $val -eq '')) { continue }
|
||||
|
||||
if ($tag -ceq 'font') {
|
||||
if ($fontMap.Contains("$val")) { $props['font'] = $fontMap["$val"] }
|
||||
continue
|
||||
}
|
||||
# wrap — не имя, а сокращение: булево вместо перечисления textPlacement.
|
||||
if ($tag -ceq 'wrap') {
|
||||
if ($val -eq $true -or "$val" -eq 'true') { $props['textPlacement'] = 'Wrap' }
|
||||
continue
|
||||
}
|
||||
if (-not $kinds.ContainsKey($tag)) {
|
||||
Write-Warning "Unknown style key '$raw' ($where) — ignored."
|
||||
continue
|
||||
}
|
||||
switch ($kinds[$tag]) {
|
||||
'line' { $props[$tag] = Register-Line (ConvertTo-LineValue $val $where) }
|
||||
'bool' { $props[$tag] = if ($val -eq $true -or "$val" -eq 'true') { 'true' } else { 'false' } }
|
||||
'int' { $props[$tag] = [int]$val }
|
||||
'enum' {
|
||||
$allowed = $enums[$tag]
|
||||
$canon = $allowed | Where-Object { $_ -eq "$val" } | Select-Object -First 1
|
||||
if (-not $canon) {
|
||||
[Console]::Error.WriteLine("Unknown '$tag' value `"$val`" ($where). Allowed: $($allowed -join ', ')")
|
||||
exit 1
|
||||
}
|
||||
$props[$tag] = $canon
|
||||
}
|
||||
default { $props[$tag] = "$val" }
|
||||
}
|
||||
}
|
||||
if ($style.valign) {
|
||||
switch ($style.valign) {
|
||||
"top" { $va = "Top" }
|
||||
"center" { $va = "Center" }
|
||||
}
|
||||
}
|
||||
|
||||
# Wrap
|
||||
if ($style.wrap -eq $true) { $wrap = $true }
|
||||
|
||||
# Number format
|
||||
if ($style.format) { $nf = $style.format }
|
||||
}
|
||||
}
|
||||
|
||||
# Набор свойств формата — «тег платформы → значение», только заданные. Порядок вставки
|
||||
# роли не играет: и ключ дедупликации, и эмиссия идут по каноническому порядку тегов.
|
||||
$props = @{ font = $fontIdx }
|
||||
if ($lb -ge 0) { $props['leftBorder'] = $lb }
|
||||
if ($tb -ge 0) { $props['topBorder'] = $tb }
|
||||
if ($rb -ge 0) { $props['rightBorder'] = $rb }
|
||||
if ($bb -ge 0) { $props['bottomBorder'] = $bb }
|
||||
if ($ha) { $props['horizontalAlignment'] = $ha }
|
||||
if ($va) { $props['verticalAlignment'] = $va }
|
||||
if ($wrap) { $props['textPlacement'] = 'Wrap' }
|
||||
if ($fillType) { $props['fillType'] = $fillType }
|
||||
if ($nf) { $props['format'] = $nf }
|
||||
|
||||
# Одинаковые четыре стороны платформа пишет одним <border>. Правило проверено на корпусе:
|
||||
# 70 265 свёрнутых форматов, 36 783 записанных по сторонам — и среди вторых нет ни одного
|
||||
# с четырьмя совпадающими значениями.
|
||||
$sides = @('leftBorder', 'topBorder', 'rightBorder', 'bottomBorder')
|
||||
$present = @($sides | Where-Object { $props.ContainsKey($_) })
|
||||
if ($present.Count -eq 4) {
|
||||
$vals = @($sides | ForEach-Object { $props[$_] } | Select-Object -Unique)
|
||||
if ($vals.Count -eq 1) {
|
||||
foreach ($s in $sides) { $props.Remove($s) }
|
||||
$props['border'] = $vals[0]
|
||||
}
|
||||
}
|
||||
return $props
|
||||
}
|
||||
|
||||
@@ -524,8 +580,74 @@ function Get-FormatMlTags {
|
||||
return @{ 'format' = $true; 'editFormat' = $true; 'mask' = $true }
|
||||
}
|
||||
|
||||
# Тип значения каждого тега — выведен из корпуса, а не выписан на глаз.
|
||||
# line — ссылка в палитру <line>; color — #RRGGBB / style: / web: / win:
|
||||
# ml — многоязычная строка; enum — замкнутый список (см. Get-FormatEnumValues)
|
||||
# containsValue / valueType / controlType сюда НЕ входят: это свойства конкретной ячейки,
|
||||
# а стиль — сущность общая, один на многие ячейки.
|
||||
function Get-FormatTagKind {
|
||||
return @{
|
||||
'autoIndent' = 'int'; 'autoMarkIncomplete' = 'bool'; 'autoWidthCalculation' = 'bool'
|
||||
'backColor' = 'color'; 'border' = 'line'; 'borderColor' = 'color'
|
||||
'bottomBorder' = 'line'; 'bySelectedColumns' = 'bool'; 'columnSizeChange' = 'enum'
|
||||
'detailsUse' = 'enum'; 'drawingBorder' = 'int'
|
||||
'drawingHaveBottomBorder' = 'bool'; 'drawingHaveLeftBorder' = 'bool'
|
||||
'drawingHaveRightBorder' = 'bool'; 'drawingHaveTopBorder' = 'bool'
|
||||
'editFormat' = 'ml'; 'fillType' = 'enum'; 'font' = 'int'; 'format' = 'ml'
|
||||
'height' = 'int'; 'hidden' = 'bool'; 'horizontalAlignment' = 'enum'
|
||||
'hyperLink' = 'bool'; 'indent' = 'int'; 'leftBorder' = 'line'
|
||||
'markNegatives' = 'bool'; 'mask' = 'ml'; 'pattern' = 'enum'; 'patternColor' = 'color'
|
||||
'picHorizontalAlignment' = 'enum'; 'picIndex' = 'int'; 'picVerticalAlignment' = 'enum'
|
||||
'pictureSizeMode' = 'enum'; 'print' = 'bool'; 'protection' = 'bool'
|
||||
'rightBorder' = 'line'; 'textColor' = 'color'; 'textOrientation' = 'int'
|
||||
'textPlacement' = 'enum'; 'textPosition' = 'enum'; 'topBorder' = 'line'
|
||||
'verticalAlignment' = 'enum'; 'width' = 'int'; 'widthWeightFactor' = 'int'
|
||||
}
|
||||
}
|
||||
|
||||
# Допустимые значения перечислений — тоже сняты с корпуса.
|
||||
function Get-FormatEnumValues {
|
||||
return @{
|
||||
'columnSizeChange' = @('Normal', 'QuickChange')
|
||||
'detailsUse' = @('Cell', 'Row', 'WithoutProcessing')
|
||||
'fillType' = @('Parameter', 'Template', 'Text')
|
||||
'horizontalAlignment' = @('Auto', 'Center', 'Justify', 'Left', 'Right')
|
||||
'pattern' = @('Pattern7', 'Pattern10', 'Pattern12', 'Pattern13', 'Pattern14', 'Pattern16', 'Solid', 'WithoutPattern')
|
||||
'picHorizontalAlignment' = @('Auto', 'Center', 'Left', 'Right')
|
||||
'picVerticalAlignment' = @('Bottom', 'Center', 'Top')
|
||||
'pictureSizeMode' = @('AutoSize', 'Proportionally', 'RealSize')
|
||||
'textPlacement' = @('Auto', 'Block', 'Cut', 'Wrap')
|
||||
'textPosition' = @('Auto', 'Bottom', 'Right', 'Top')
|
||||
'verticalAlignment' = @('Bottom', 'Center', 'Top')
|
||||
}
|
||||
}
|
||||
|
||||
# Прощающий ввод: ключ стиля, написанный иначе, чем тег платформы. Канон побеждает —
|
||||
# если заданы оба, синоним отбрасывается. Ключи карты нормализованы (lower, без пробелов).
|
||||
# Инвертированных синонимов (visible для hidden) НЕ заводим — это баг семантики, не удобство.
|
||||
function Get-StyleKeySynonyms {
|
||||
return @{
|
||||
'align' = 'horizontalAlignment'; 'textalign' = 'horizontalAlignment'
|
||||
'halign' = 'horizontalAlignment'; 'горизонтальноеположение' = 'horizontalAlignment'
|
||||
'valign' = 'verticalAlignment'; 'verticalalign' = 'verticalAlignment'
|
||||
'вертикальноеположение' = 'verticalAlignment'
|
||||
'background' = 'backColor'; 'bgcolor' = 'backColor'; 'цветфона' = 'backColor'
|
||||
'color' = 'textColor'; 'forecolor' = 'textColor'; 'цветтекста' = 'textColor'
|
||||
'цветрамки' = 'borderColor'; 'цветузора' = 'patternColor'
|
||||
'borderleft' = 'leftBorder'; 'border-left' = 'leftBorder'
|
||||
'bordertop' = 'topBorder'; 'border-top' = 'topBorder'
|
||||
'borderright' = 'rightBorder'; 'border-right' = 'rightBorder'
|
||||
'borderbottom' = 'bottomBorder'; 'border-bottom' = 'bottomBorder'
|
||||
'protected' = 'protection'; 'защита' = 'protection'
|
||||
'отступ' = 'indent'; 'узор' = 'pattern'; 'гиперссылка' = 'hyperLink'
|
||||
'ориентациятекста' = 'textOrientation'; 'размещениетекста' = 'textPlacement'
|
||||
'переноспословам' = 'wrap'
|
||||
}
|
||||
}
|
||||
|
||||
$script:formatTagOrder = Get-FormatTagOrder
|
||||
$script:formatMlTags = Get-FormatMlTags
|
||||
$script:formatTagKind = Get-FormatTagKind
|
||||
|
||||
function Get-FormatKey {
|
||||
param([hashtable]$props)
|
||||
@@ -1315,14 +1437,9 @@ foreach ($ni in $sortedNamedItems) {
|
||||
}
|
||||
|
||||
# 7h. Line palette
|
||||
if ($hasThinBorders) {
|
||||
X "`t<line width=`"1`" gap=`"false`">"
|
||||
X "`t`t<v8ui:style xsi:type=`"v8ui:SpreadsheetDocumentCellLineType`">Solid</v8ui:style>"
|
||||
X "`t</line>"
|
||||
}
|
||||
if ($hasThickBorders) {
|
||||
X "`t<line width=`"2`" gap=`"false`">"
|
||||
X "`t`t<v8ui:style xsi:type=`"v8ui:SpreadsheetDocumentCellLineType`">Solid</v8ui:style>"
|
||||
foreach ($ln in $script:lineRegistry) {
|
||||
X "`t<line width=`"$($ln.Width)`" gap=`"$($ln.Gap)`">"
|
||||
X "`t`t<v8ui:style xsi:type=`"v8ui:SpreadsheetDocumentCellLineType`">$($ln.Style)</v8ui:style>"
|
||||
X "`t</line>"
|
||||
}
|
||||
|
||||
@@ -1346,6 +1463,12 @@ foreach ($key in $formatRegistry.Keys) {
|
||||
X "`t`t`t`t<v8:content>$(Esc-XmlText $val)</v8:content>"
|
||||
X "`t`t`t</v8:item>"
|
||||
X "`t`t</$tag>"
|
||||
} elseif ($script:formatTagKind[$tag] -ceq 'color' -and (Get-ColorNamespace "$val")) {
|
||||
# web/win-палитры в корне документа не объявлены — платформа дописывает объявление
|
||||
# прямо на узел и пишет значение с этим префиксом.
|
||||
$ns = Get-ColorNamespace "$val"
|
||||
$name = "$val".Substring("$val".IndexOf(':') + 1)
|
||||
X "`t`t<$tag xmlns:d3p1=`"$ns`">d3p1:$name</$tag>"
|
||||
} else {
|
||||
X "`t`t<$tag>$val</$tag>"
|
||||
}
|
||||
@@ -1376,5 +1499,5 @@ if ($def.page) {
|
||||
Write-Host " Page: $pageName -> target $targetWidth, defaultWidth=$defaultWidth"
|
||||
}
|
||||
Write-Host " Areas: $($namedItems.Count), Rows: $totalRowCount, Columns: $totalColumns"
|
||||
Write-Host " Fonts: $($fontEntries.Count), Lines: $lineCount, Formats: $($formatRegistry.Count)"
|
||||
Write-Host " Fonts: $($fontEntries.Count), Lines: $($script:lineRegistry.Count), Formats: $($formatRegistry.Count)"
|
||||
Write-Host " Merges: $($merges.Count)"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-compile v1.28 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.29 — Compile 1C spreadsheet from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import hashlib
|
||||
@@ -350,6 +350,87 @@ def format_ml_tags():
|
||||
return {'format': True, 'editFormat': True, 'mask': True}
|
||||
|
||||
|
||||
def format_tag_kind():
|
||||
"""Тип значения каждого тега — выведен из корпуса, а не выписан на глаз.
|
||||
line — ссылка в палитру <line>; color — #RRGGBB / style: / web: / win:
|
||||
ml — многоязычная строка; enum — замкнутый список (см. format_enum_values).
|
||||
containsValue / valueType / controlType сюда НЕ входят: это свойства конкретной ячейки,
|
||||
а стиль — сущность общая, один на многие ячейки."""
|
||||
return {
|
||||
'autoIndent': 'int', 'autoMarkIncomplete': 'bool', 'autoWidthCalculation': 'bool',
|
||||
'backColor': 'color', 'border': 'line', 'borderColor': 'color',
|
||||
'bottomBorder': 'line', 'bySelectedColumns': 'bool', 'columnSizeChange': 'enum',
|
||||
'detailsUse': 'enum', 'drawingBorder': 'int',
|
||||
'drawingHaveBottomBorder': 'bool', 'drawingHaveLeftBorder': 'bool',
|
||||
'drawingHaveRightBorder': 'bool', 'drawingHaveTopBorder': 'bool',
|
||||
'editFormat': 'ml', 'fillType': 'enum', 'font': 'int', 'format': 'ml',
|
||||
'height': 'int', 'hidden': 'bool', 'horizontalAlignment': 'enum',
|
||||
'hyperLink': 'bool', 'indent': 'int', 'leftBorder': 'line',
|
||||
'markNegatives': 'bool', 'mask': 'ml', 'pattern': 'enum', 'patternColor': 'color',
|
||||
'picHorizontalAlignment': 'enum', 'picIndex': 'int', 'picVerticalAlignment': 'enum',
|
||||
'pictureSizeMode': 'enum', 'print': 'bool', 'protection': 'bool',
|
||||
'rightBorder': 'line', 'textColor': 'color', 'textOrientation': 'int',
|
||||
'textPlacement': 'enum', 'textPosition': 'enum', 'topBorder': 'line',
|
||||
'verticalAlignment': 'enum', 'width': 'int', 'widthWeightFactor': 'int',
|
||||
}
|
||||
|
||||
|
||||
def format_enum_values():
|
||||
"""Допустимые значения перечислений — тоже сняты с корпуса."""
|
||||
return {
|
||||
'columnSizeChange': ['Normal', 'QuickChange'],
|
||||
'detailsUse': ['Cell', 'Row', 'WithoutProcessing'],
|
||||
'fillType': ['Parameter', 'Template', 'Text'],
|
||||
'horizontalAlignment': ['Auto', 'Center', 'Justify', 'Left', 'Right'],
|
||||
'pattern': ['Pattern7', 'Pattern10', 'Pattern12', 'Pattern13', 'Pattern14',
|
||||
'Pattern16', 'Solid', 'WithoutPattern'],
|
||||
'picHorizontalAlignment': ['Auto', 'Center', 'Left', 'Right'],
|
||||
'picVerticalAlignment': ['Bottom', 'Center', 'Top'],
|
||||
'pictureSizeMode': ['AutoSize', 'Proportionally', 'RealSize'],
|
||||
'textPlacement': ['Auto', 'Block', 'Cut', 'Wrap'],
|
||||
'textPosition': ['Auto', 'Bottom', 'Right', 'Top'],
|
||||
'verticalAlignment': ['Bottom', 'Center', 'Top'],
|
||||
}
|
||||
|
||||
|
||||
def style_key_synonyms():
|
||||
"""Прощающий ввод: ключ стиля, написанный иначе, чем тег платформы. Канон побеждает —
|
||||
если заданы оба, синоним отбрасывается. Ключи карты нормализованы (lower, без пробелов).
|
||||
Инвертированных синонимов (visible для hidden) НЕ заводим — это баг семантики, не удобство."""
|
||||
return {
|
||||
'align': 'horizontalAlignment', 'textalign': 'horizontalAlignment',
|
||||
'halign': 'horizontalAlignment', 'горизонтальноеположение': 'horizontalAlignment',
|
||||
'valign': 'verticalAlignment', 'verticalalign': 'verticalAlignment',
|
||||
'вертикальноеположение': 'verticalAlignment',
|
||||
'background': 'backColor', 'bgcolor': 'backColor', 'цветфона': 'backColor',
|
||||
'color': 'textColor', 'forecolor': 'textColor', 'цветтекста': 'textColor',
|
||||
'цветрамки': 'borderColor', 'цветузора': 'patternColor',
|
||||
'borderleft': 'leftBorder', 'border-left': 'leftBorder',
|
||||
'bordertop': 'topBorder', 'border-top': 'topBorder',
|
||||
'borderright': 'rightBorder', 'border-right': 'rightBorder',
|
||||
'borderbottom': 'bottomBorder', 'border-bottom': 'bottomBorder',
|
||||
'protected': 'protection', 'защита': 'protection',
|
||||
'отступ': 'indent', 'узор': 'pattern', 'гиперссылка': 'hyperLink',
|
||||
'ориентациятекста': 'textOrientation', 'размещениетекста': 'textPlacement',
|
||||
'переноспословам': 'wrap',
|
||||
}
|
||||
|
||||
|
||||
def line_styles():
|
||||
"""Стили линии, встречающиеся в палитрах корпуса."""
|
||||
return ['Solid', 'None', 'Dotted', 'ThinDashed', 'LargeDashed', 'ThickDashed', 'Double']
|
||||
|
||||
|
||||
def color_namespace(val):
|
||||
"""Цвет — значение с префиксом пространства имён (нотация платформы). style: объявлен
|
||||
в корне документа, web/win — нет, поэтому платформа дописывает объявление прямо на узел."""
|
||||
if val.startswith('web:'):
|
||||
return 'http://v8.1c.ru/8.1/data/ui/colors/web'
|
||||
if val.startswith('win:'):
|
||||
return 'http://v8.1c.ru/8.1/data/ui/colors/windows'
|
||||
return ''
|
||||
|
||||
|
||||
def get_format_key(props):
|
||||
parts = []
|
||||
for tag in format_tag_order():
|
||||
@@ -430,27 +511,18 @@ def main():
|
||||
if not has_default:
|
||||
add_font('default', {'face': 'Arial', 'size': 10})
|
||||
|
||||
# --- 3. Determine line palette ---
|
||||
has_thin_borders = False
|
||||
has_thick_borders = False
|
||||
# --- 3. Line palette ---
|
||||
# Рамка хранится не в формате, а в палитре <line>: формат ссылается на запись индексом.
|
||||
# Запись — тройка (стиль, ширина, gap); в корпусе gap всегда false, но тег платформа пишет.
|
||||
line_registry = []
|
||||
|
||||
if defn.get('styles'):
|
||||
for sname, sval in defn['styles'].items():
|
||||
if sval.get('border') and sval['border'] != 'none':
|
||||
if sval.get('borderWidth') == 'thick':
|
||||
has_thick_borders = True
|
||||
else:
|
||||
has_thin_borders = True
|
||||
|
||||
thin_line_index = -1
|
||||
thick_line_index = -1
|
||||
line_count = 0
|
||||
if has_thin_borders:
|
||||
thin_line_index = line_count
|
||||
line_count += 1
|
||||
if has_thick_borders:
|
||||
thick_line_index = line_count
|
||||
line_count += 1
|
||||
def register_line(ln):
|
||||
key = (ln['Style'], str(ln['Width']), ln['Gap'])
|
||||
for i, existing in enumerate(line_registry):
|
||||
if (existing['Style'], str(existing['Width']), existing['Gap']) == key:
|
||||
return i
|
||||
line_registry.append(ln)
|
||||
return len(line_registry) - 1
|
||||
|
||||
# --- 4. Parse column width specs ---
|
||||
def parse_column_spec(spec):
|
||||
@@ -555,72 +627,121 @@ def main():
|
||||
})
|
||||
|
||||
# --- 5. Style resolver ---
|
||||
def to_line_value(val, where):
|
||||
"""Значение рамки: строка стиля ("Dotted") либо объект { style, width, gap }.
|
||||
Прежняя запись borderWidth: thin/thick — это ширина 1 и 2."""
|
||||
style, width, gap = 'Solid', 1, 'false'
|
||||
if isinstance(val, dict):
|
||||
if val.get('style') is not None:
|
||||
style = str(val['style'])
|
||||
if val.get('width') is not None:
|
||||
width = val['width']
|
||||
if val.get('gap') is not None:
|
||||
gap = 'true' if val['gap'] is True else 'false'
|
||||
else:
|
||||
style = str(val)
|
||||
if style == 'thin':
|
||||
style, width = 'Solid', 1
|
||||
elif style == 'thick':
|
||||
style, width = 'Solid', 2
|
||||
canon = next((s for s in line_styles() if s.lower() == style.lower()), None)
|
||||
if not canon:
|
||||
print(f'Unknown border style "{style}" ({where}). Allowed: {", ".join(line_styles())}',
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
return {'Style': canon, 'Width': width, 'Gap': gap}
|
||||
|
||||
def resolve_style(style_name, fill_type):
|
||||
font_idx = font_map.get('default', 0)
|
||||
lb = -1; tb = -1; rb = -1; bb = -1
|
||||
ha = ''; va = ''; nf = ''
|
||||
wrap = False
|
||||
# Набор свойств формата — «тег платформы → значение», только заданные. Порядок вставки
|
||||
# роли не играет: и ключ дедупликации, и эмиссия идут по каноническому порядку тегов.
|
||||
props = {'font': font_map.get('default', 0)}
|
||||
|
||||
if style_name and defn.get('styles'):
|
||||
style = defn['styles'].get(style_name)
|
||||
if style:
|
||||
# Font
|
||||
if style.get('font') and style['font'] in font_map:
|
||||
font_idx = font_map[style['font']]
|
||||
kinds = format_tag_kind()
|
||||
enums = format_enum_values()
|
||||
synonyms = style_key_synonyms()
|
||||
where = f'style "{style_name}"'
|
||||
side_keys = {'left': 'leftBorder', 'top': 'topBorder',
|
||||
'right': 'rightBorder', 'bottom': 'bottomBorder'}
|
||||
|
||||
# Borders
|
||||
if style.get('border') and style['border'] != 'none':
|
||||
line_idx = thick_line_index if style.get('borderWidth') == 'thick' else thin_line_index
|
||||
for side in style['border'].split(','):
|
||||
side = side.strip()
|
||||
if side == 'all':
|
||||
lb = line_idx; tb = line_idx; rb = line_idx; bb = line_idx
|
||||
elif side == 'left':
|
||||
lb = line_idx
|
||||
elif side == 'top':
|
||||
tb = line_idx
|
||||
elif side == 'right':
|
||||
rb = line_idx
|
||||
elif side == 'bottom':
|
||||
bb = line_idx
|
||||
# Прежняя запись рамки: стороны строкой + borderWidth. Разворачиваем в
|
||||
# посторонние ключи ДО общего разбора, чтобы дальше был один путь.
|
||||
legacy = style.get('border')
|
||||
legacy_sides = (isinstance(legacy, str) and legacy
|
||||
and not any(s.lower() == legacy.lower() for s in line_styles()))
|
||||
if legacy_sides:
|
||||
idx = register_line(to_line_value(
|
||||
{'style': 'Solid', 'width': 2 if str(style.get('borderWidth')) == 'thick' else 1},
|
||||
where))
|
||||
for side in legacy.split(','):
|
||||
s = side.strip().lower()
|
||||
if s == 'none':
|
||||
continue
|
||||
if s == 'all':
|
||||
for k in side_keys.values():
|
||||
props[k] = idx
|
||||
elif s in side_keys:
|
||||
props[side_keys[s]] = idx
|
||||
else:
|
||||
print(f'Unknown border side "{side.strip()}" ({where}).'
|
||||
f' Allowed: all, left, top, right, bottom, none', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Alignment
|
||||
if style.get('align'):
|
||||
align_map = {'left': 'Left', 'center': 'Center', 'right': 'Right'}
|
||||
ha = align_map.get(style['align'], '')
|
||||
if style.get('valign'):
|
||||
valign_map = {'top': 'Top', 'center': 'Center'}
|
||||
va = valign_map.get(style['valign'], '')
|
||||
for raw, val in style.items():
|
||||
# Синонимы: канон побеждает, сравнение без регистра и пробелов.
|
||||
norm = re.sub(r'\s', '', raw).lower()
|
||||
tag = synonyms.get(norm, raw)
|
||||
if tag == 'borderWidth':
|
||||
continue
|
||||
if tag == 'border' and legacy_sides:
|
||||
continue
|
||||
if val is None or (isinstance(val, str) and val == ''):
|
||||
continue
|
||||
|
||||
# Wrap
|
||||
if style.get('wrap') is True:
|
||||
wrap = True
|
||||
if tag == 'font':
|
||||
if str(val) in font_map:
|
||||
props['font'] = font_map[str(val)]
|
||||
continue
|
||||
# wrap — не имя, а сокращение: булево вместо перечисления textPlacement.
|
||||
if tag == 'wrap':
|
||||
if val is True or str(val) == 'true':
|
||||
props['textPlacement'] = 'Wrap'
|
||||
continue
|
||||
if tag not in kinds:
|
||||
print(f"Warning: unknown style key '{raw}' ({where}) — ignored.", file=sys.stderr)
|
||||
continue
|
||||
kind = kinds[tag]
|
||||
if kind == 'line':
|
||||
props[tag] = register_line(to_line_value(val, where))
|
||||
elif kind == 'bool':
|
||||
props[tag] = 'true' if (val is True or str(val) == 'true') else 'false'
|
||||
elif kind == 'int':
|
||||
props[tag] = int(val)
|
||||
elif kind == 'enum':
|
||||
allowed = enums[tag]
|
||||
canon = next((a for a in allowed if a.lower() == str(val).lower()), None)
|
||||
if not canon:
|
||||
print(f'Unknown \'{tag}\' value "{val}" ({where}).'
|
||||
f' Allowed: {", ".join(allowed)}', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
props[tag] = canon
|
||||
else:
|
||||
props[tag] = str(val)
|
||||
|
||||
# Number format
|
||||
if style.get('format'):
|
||||
nf = style['format']
|
||||
|
||||
# Набор свойств формата — «тег платформы → значение», только заданные. Порядок вставки
|
||||
# роли не играет: и ключ дедупликации, и эмиссия идут по каноническому порядку тегов.
|
||||
props = {'font': font_idx}
|
||||
if lb >= 0:
|
||||
props['leftBorder'] = lb
|
||||
if tb >= 0:
|
||||
props['topBorder'] = tb
|
||||
if rb >= 0:
|
||||
props['rightBorder'] = rb
|
||||
if bb >= 0:
|
||||
props['bottomBorder'] = bb
|
||||
if ha:
|
||||
props['horizontalAlignment'] = ha
|
||||
if va:
|
||||
props['verticalAlignment'] = va
|
||||
if wrap:
|
||||
props['textPlacement'] = 'Wrap'
|
||||
if fill_type:
|
||||
props['fillType'] = fill_type
|
||||
if nf:
|
||||
props['format'] = nf
|
||||
|
||||
# Одинаковые четыре стороны платформа пишет одним <border>. Правило проверено на корпусе:
|
||||
# 70 265 свёрнутых форматов, 36 783 записанных по сторонам — и среди вторых нет ни одного
|
||||
# с четырьмя совпадающими значениями.
|
||||
sides = ['leftBorder', 'topBorder', 'rightBorder', 'bottomBorder']
|
||||
if all(s in props for s in sides) and len({props[s] for s in sides}) == 1:
|
||||
val = props[sides[0]]
|
||||
for s in sides:
|
||||
del props[s]
|
||||
props['border'] = val
|
||||
return props
|
||||
|
||||
# --- 6. Format palette builder ---
|
||||
@@ -1294,13 +1415,9 @@ def main():
|
||||
lines.append('\t</namedItem>')
|
||||
|
||||
# 7h. Line palette
|
||||
if has_thin_borders:
|
||||
lines.append('\t<line width="1" gap="false">')
|
||||
lines.append('\t\t<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>')
|
||||
lines.append('\t</line>')
|
||||
if has_thick_borders:
|
||||
lines.append('\t<line width="2" gap="false">')
|
||||
lines.append('\t\t<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>')
|
||||
for ln in line_registry:
|
||||
lines.append(f'\t<line width="{ln["Width"]}" gap="{ln["Gap"]}">')
|
||||
lines.append(f'\t\t<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">{ln["Style"]}</v8ui:style>')
|
||||
lines.append('\t</line>')
|
||||
|
||||
# 7i. Font palette
|
||||
@@ -1313,6 +1430,7 @@ def main():
|
||||
lines.append('\t<format>')
|
||||
|
||||
ml_tags = format_ml_tags()
|
||||
kinds = format_tag_kind()
|
||||
for tag in format_tag_order():
|
||||
if tag not in fmt:
|
||||
continue
|
||||
@@ -1324,6 +1442,12 @@ def main():
|
||||
lines.append(f'\t\t\t\t<v8:content>{esc_xml_text(val)}</v8:content>')
|
||||
lines.append('\t\t\t</v8:item>')
|
||||
lines.append(f'\t\t</{tag}>')
|
||||
elif kinds.get(tag) == 'color' and color_namespace(str(val)):
|
||||
# web/win-палитры в корне документа не объявлены — платформа дописывает
|
||||
# объявление прямо на узел и пишет значение с этим префиксом.
|
||||
ns = color_namespace(str(val))
|
||||
name = str(val)[str(val).index(':') + 1:]
|
||||
lines.append(f'\t\t<{tag} xmlns:d3p1="{ns}">d3p1:{name}</{tag}>')
|
||||
else:
|
||||
lines.append(f'\t\t<{tag}>{val}</{tag}>')
|
||||
|
||||
@@ -1351,7 +1475,7 @@ def main():
|
||||
if defn.get('page'):
|
||||
print(f" Page: {page_name} -> target {target_width}, defaultWidth={default_width}")
|
||||
print(f" Areas: {len(named_items)}, Rows: {total_row_count}, Columns: {total_columns}")
|
||||
print(f" Fonts: {len(font_entries)}, Lines: {line_count}, Formats: {len(format_registry)}")
|
||||
print(f" Fonts: {len(font_entries)}, Lines: {len(line_registry)}, Formats: {len(format_registry)}")
|
||||
print(f" Merges: {len(merges)}")
|
||||
|
||||
|
||||
|
||||
@@ -151,9 +151,6 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
</format>
|
||||
</document>
|
||||
@@ -101,17 +101,11 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
</document>
|
||||
@@ -123,25 +123,16 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
<fillType>Parameter</fillType>
|
||||
<format>
|
||||
@@ -153,18 +144,12 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Right</horizontalAlignment>
|
||||
<fillType>Parameter</fillType>
|
||||
<format>
|
||||
|
||||
@@ -159,42 +159,27 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
</format>
|
||||
<format>
|
||||
<font>1</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
</document>
|
||||
@@ -194,25 +194,16 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Right</horizontalAlignment>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
|
||||
@@ -174,34 +174,22 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>1</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
</document>
|
||||
@@ -140,17 +140,11 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
</document>
|
||||
@@ -548,42 +548,27 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Right</horizontalAlignment>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
|
||||
@@ -117,10 +117,7 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,153 @@
|
||||
<?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>4</size>
|
||||
</columns>
|
||||
<rowsItem>
|
||||
<index>0</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>2</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>
|
||||
<c>
|
||||
<c>
|
||||
<f>3</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Слева пунктир</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>4</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Цвет из палитры</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>5</f>
|
||||
<parameter>Скрытое</parameter>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<c>
|
||||
<f>6</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Рамка свёрнута</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>1</defaultFormatIndex>
|
||||
<height>2</height>
|
||||
<vgRows>2</vgRows>
|
||||
<merge>
|
||||
<r>0</r>
|
||||
<c>0</c>
|
||||
<w>3</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>
|
||||
<line width="1" gap="false">
|
||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Dotted</v8ui:style>
|
||||
</line>
|
||||
<line width="2" gap="false">
|
||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||
</line>
|
||||
<line width="1" gap="false">
|
||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">ThinDashed</v8ui:style>
|
||||
</line>
|
||||
<line width="1" gap="false">
|
||||
<v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">Solid</v8ui:style>
|
||||
</line>
|
||||
<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>
|
||||
<font>1</font>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
<verticalAlignment>Center</verticalAlignment>
|
||||
<textColor>style:FormTextColor</textColor>
|
||||
<backColor>#EBEBEB</backColor>
|
||||
<textPlacement>Wrap</textPlacement>
|
||||
<protection>true</protection>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>1</topBorder>
|
||||
<bottomBorder>2</bottomBorder>
|
||||
<borderColor>#C8C8C8</borderColor>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<textColor xmlns:d3p1="http://v8.1c.ru/8.1/data/ui/colors/windows">d3p1:ButtonText</textColor>
|
||||
<backColor xmlns:d3p1="http://v8.1c.ru/8.1/data/ui/colors/web">d3p1:Gainsboro</backColor>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<fillType>Parameter</fillType>
|
||||
<hidden>true</hidden>
|
||||
<textOrientation>900</textOrientation>
|
||||
<indent>2</indent>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<border>3</border>
|
||||
</format>
|
||||
</document>
|
||||
@@ -302,42 +302,27 @@
|
||||
</format>
|
||||
<format>
|
||||
<font>1</font>
|
||||
<leftBorder>1</leftBorder>
|
||||
<topBorder>1</topBorder>
|
||||
<rightBorder>1</rightBorder>
|
||||
<bottomBorder>1</bottomBorder>
|
||||
<border>1</border>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Center</horizontalAlignment>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<textPlacement>Wrap</textPlacement>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<leftBorder>0</leftBorder>
|
||||
<topBorder>0</topBorder>
|
||||
<rightBorder>0</rightBorder>
|
||||
<bottomBorder>0</bottomBorder>
|
||||
<border>0</border>
|
||||
<horizontalAlignment>Right</horizontalAlignment>
|
||||
<fillType>Parameter</fillType>
|
||||
</format>
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "Стиль: свойства формата платформенными именами, цвета, посторонние рамки",
|
||||
"input": {
|
||||
"columns": 4,
|
||||
"defaultWidth": 20,
|
||||
"fonts": {
|
||||
"default": { "face": "Arial", "size": 10 },
|
||||
"bold": { "face": "Arial", "size": 10, "bold": true }
|
||||
},
|
||||
"styles": {
|
||||
"шапка": {
|
||||
"font": "bold",
|
||||
"backColor": "#EBEBEB",
|
||||
"textColor": "style:FormTextColor",
|
||||
"horizontalAlignment": "Center",
|
||||
"verticalAlignment": "Center",
|
||||
"textPlacement": "Wrap",
|
||||
"protection": true
|
||||
},
|
||||
"рамка-по-сторонам": {
|
||||
"leftBorder": "Dotted",
|
||||
"topBorder": { "style": "Solid", "width": 2 },
|
||||
"bottomBorder": { "style": "ThinDashed" },
|
||||
"borderColor": "#C8C8C8"
|
||||
},
|
||||
"web-цвет": {
|
||||
"backColor": "web:Gainsboro",
|
||||
"textColor": "win:ButtonText"
|
||||
},
|
||||
"скрытая": {
|
||||
"hidden": true,
|
||||
"indent": 2,
|
||||
"textOrientation": 900
|
||||
},
|
||||
"рамка-вокруг": {
|
||||
"leftBorder": "Solid",
|
||||
"topBorder": "Solid",
|
||||
"rightBorder": "Solid",
|
||||
"bottomBorder": "Solid"
|
||||
}
|
||||
},
|
||||
"areas": [
|
||||
{
|
||||
"name": "Шапка",
|
||||
"rows": [
|
||||
{ "cells": [
|
||||
{ "col": 1, "span": 4, "style": "шапка", "text": "Отчёт о движении" }
|
||||
]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Тело",
|
||||
"rows": [
|
||||
{ "cells": [
|
||||
{ "col": 1, "style": "рамка-по-сторонам", "text": "Слева пунктир" },
|
||||
{ "col": 2, "style": "web-цвет", "text": "Цвет из палитры" },
|
||||
{ "col": 3, "style": "скрытая", "param": "Скрытое" },
|
||||
{ "col": 4, "style": "рамка-вокруг", "text": "Рамка свёрнута" }
|
||||
]}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": { "outputPath": "Template.xml" },
|
||||
"validatePath": "Template.xml",
|
||||
"expect": { "files": ["Template.xml"] }
|
||||
}
|
||||
Reference in New Issue
Block a user