Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions excelizestyle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Typed Excelize styles

`StyleDefinition` and its nested definitions represent every public field of the
selected Excelize `Style`, `Border`, `Fill`, `Font`, `Alignment`, and `Protection`
structs. Categorical fields use named enum types. Numeric, text, boolean, and
pointer values retain their original meaning and can express custom values.

```go
style := excelizestyle.StyleDefinition{
Fill: excelizestyle.FillDefinition{
Type: excelizestyle.FillTypePattern,
Pattern: excelizestyle.FillPatternSolid,
Color: []string{"#123456"},
},
Alignment: &excelizestyle.AlignmentDefinition{
Horizontal: excelizestyle.AlignmentHorizontalCenter,
Vertical: excelizestyle.AlignmentVerticalBottom,
ReadingOrder: excelizestyle.AlignmentReadingOrderLeftToRight,
},
NumFmt: excelizestyle.NumberFormatID14,
}
styleID, err := workbook.NewStyle(style.ToExcelize())
```

Use `StyleDefinitionFromExcelize` to convert existing styles, or
`excelizeutil.GetStyleDefinition` to read a cell into this representation.
Conversion between a definition and an `excelize.Style` preserves all struct
fields, including nil pointers, custom strings, unknown numeric enum values,
and the distinction between nil and empty border slices. This does not expand
what Excelize can serialize or recover from a workbook. In particular, cell fill
transparency, arbitrary gradient shapes, both pattern colors, and the original
`Lang`/`DecimalPlaces`/`NegRed` inputs cannot always be recovered.

## Generation and dependency updates

After updating Excelize, run from the repository root:

```sh
go generate ./excelizeutil
```

The generator reads the selected dependency through Go AST:

- Fill pattern, border style and position, and fill type tables.
- Gradient preset IDs, geometry, and stop positions (legacy switches and modern
preset literals). The extractor uses these generated geometries.
- Documented alignment choices, underline and font vertical-alignment choices.
- Built-in, currency, and language-specific number format IDs/codes and language
tags. `NumberFormat.CodeForLanguage` resolves the corresponding source table;
these codes describe Excelize inputs, not arbitrary workbook custom formats
that may reuse the same ID.
- Every public field name and the complete typed definitions/conversions.

Reading order, theme slots, character sets, and alignment defaults missing from
older documentation use stable OOXML definitions. Indexed palette values are
read from Excelize's palette when available; older releases use the 64-slot
OOXML palette. These schema definitions are explicit: AST cannot discover value
domains that Excelize does not define in code. Arbitrary RGB, font family/size,
indentation, rotation, tint, custom format, and transparency values remain plain
values rather than exhaustive enum lists.

The test suite also compares the generated files with the selected dependency,
so adding an upstream enum value or field without regenerating fails tests.

Check generation without changing files:

```sh
(cd excelizeutil && go run ./cmd/gen-style-enums -check)
```

Changes to unsupported source shapes cause generation to fail. Regeneration
updates definitions and enum tables; newly added fields still require a review
of the workbook extractor and its coverage. Tests check field inventories,
conversion of every field, upstream additions, source-shape failures, and
round-trips for all generated patterns, borders, and gradient presets.

The existing `Border`, `BorderAround`, `FindBorder`, `Alignment`, and `Fill`
helpers remain available, along with the original `BorderStyleContinuous*`,
`BorderStyleDash*`, and related aliases.
120 changes: 45 additions & 75 deletions excelizestyle/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,57 @@ import (
"github.com/xuri/excelize/v2"
)

type BorderPosition string

const (
BorderPositionTop BorderPosition = "top"
BorderPositionLeft BorderPosition = "left"
BorderPositionRight BorderPosition = "right"
BorderPositionBottom BorderPosition = "bottom"
)

// BorderStyle https://xuri.me/excelize/ja/style.html#border
type BorderStyle int

// Preserve the existing border style names as aliases of the generated enums.
const (
BorderStyleNone BorderStyle = 0 // Weight: 0, Style:
BorderStyleContinuous0 BorderStyle = 7 // Weight: 0, Style: -----------
BorderStyleContinuous1 BorderStyle = 1 // Weight: 1, Style: -----------
BorderStyleContinuous2 BorderStyle = 2 // Weight: 2, Style: -----------
BorderStyleContinuous3 BorderStyle = 5 // Weight: 3, Style: -----------
BorderStyleDash1 BorderStyle = 3 // Weight: 1, Style: - - - - - -
BorderStyleDash2 BorderStyle = 8 // Weight: 2, Style: - - - - - -
BorderStyleDot BorderStyle = 4 // Weight: 1, Style: . . . . . .
BorderStyleDouble BorderStyle = 6 // Weight: 3, Style: ===========
BorderStyleDashDot1 BorderStyle = 9 // Weight: 1, Style: - . - . - .
BorderStyleDashDot2 BorderStyle = 10 // Weight: 2, Style: - . - . - .
BorderStyleDashDotDot1 BorderStyle = 11 // Weight: 1, Style: - . . - . .
BorderStyleDashDotDot2 BorderStyle = 12 // Weight: 2, Style: - . . - . .
BorderStyleSlantDash BorderStyle = 13 // Weight: 2, Style: / - . / - .
// BorderStyleContinuous0 is the compatibility alias for BorderStyleHair.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleContinuous0 = BorderStyleHair
// BorderStyleContinuous1 is the compatibility alias for BorderStyleThin.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleContinuous1 = BorderStyleThin
// BorderStyleContinuous2 is the compatibility alias for BorderStyleMedium.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleContinuous2 = BorderStyleMedium
// BorderStyleContinuous3 is the compatibility alias for BorderStyleThick.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleContinuous3 = BorderStyleThick
// BorderStyleDash1 is the compatibility alias for BorderStyleDashed.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleDash1 = BorderStyleDashed
// BorderStyleDash2 is the compatibility alias for BorderStyleMediumDashed.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleDash2 = BorderStyleMediumDashed
// BorderStyleDot is the compatibility alias for BorderStyleDotted.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleDot = BorderStyleDotted
// BorderStyleDashDot1 is the compatibility alias for BorderStyleDashDot.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleDashDot1 = BorderStyleDashDot
// BorderStyleDashDot2 is the compatibility alias for BorderStyleMediumDashDot.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleDashDot2 = BorderStyleMediumDashDot
// BorderStyleDashDotDot1 is the compatibility alias for BorderStyleDashDotDot.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleDashDotDot1 = BorderStyleDashDotDot
// BorderStyleDashDotDot2 is the compatibility alias for BorderStyleMediumDashDotDot.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleDashDotDot2 = BorderStyleMediumDashDotDot
// BorderStyleSlantDash is the compatibility alias for BorderStyleSlantDashDot.
// See https://xuri.me/excelize/en/style.html#border
BorderStyleSlantDash = BorderStyleSlantDashDot
)

// BorderColor specifies an RGB border color, including custom hexadecimal values.
//
// See https://xuri.me/excelize/en/style.html#border
type BorderColor string

const (
// BorderColorBlack selects the RGB color black (#000000).
// See https://xuri.me/excelize/en/style.html#border
BorderColorBlack BorderColor = "#000000"
// BorderColorWhite selects the RGB color white (#FFFFFF).
// See https://xuri.me/excelize/en/style.html#border
BorderColorWhite BorderColor = "#FFFFFF"
)

Expand Down Expand Up @@ -91,29 +109,6 @@ func ExistsBorder(borders []excelize.Border, position BorderPosition) bool {
return false
}

// AlignmentHorizontal https://xuri.me/excelize/ja/style.html#align
type AlignmentHorizontal string

const (
AlignmentHorizontalLeft AlignmentHorizontal = "left" // Left (indented)
AlignmentHorizontalCenter AlignmentHorizontal = "center" // Centered
AlignmentHorizontalRight AlignmentHorizontal = "right" // Right (indented)
AlignmentHorizontalFill AlignmentHorizontal = "fill" // Filling
AlignmentHorizontalJustify AlignmentHorizontal = "justify" // Justified
AlignmentHorizontalCenterContinuous AlignmentHorizontal = "centerContinuous" // Cross-column centered
AlignmentHorizontalDistributed AlignmentHorizontal = "distributed" // Decentralized alignment (indented)
)

// AlignmentVertical https://xuri.me/excelize/ja/style.html#align
type AlignmentVertical string

const (
AlignmentVerticalTop AlignmentVertical = "top" // Top alignment
AlignmentVerticalCenter AlignmentVertical = "center" // Centered
AlignmentVerticalJustify AlignmentVertical = "justify" // Justified
AlignmentVerticalDistributed AlignmentVertical = "distributed" // Decentralized alignment
)

func Alignment(horizontal AlignmentHorizontal, vertical AlignmentVertical, wrapText bool) *excelize.Alignment {
return &excelize.Alignment{
Horizontal: string(horizontal),
Expand All @@ -122,34 +117,9 @@ func Alignment(horizontal AlignmentHorizontal, vertical AlignmentVertical, wrapT
}
}

// FillPattern https://xuri.me/excelize/ja/style.html#pattern
type FillPattern int

const (
FillPatternNone FillPattern = 0
FillPatternSolid FillPattern = 1
FillPatternMediumGray FillPattern = 2
FillPatternDarkGray FillPattern = 3
FillPatternLightGray FillPattern = 4
FillPatternDarkHorizontal FillPattern = 5
FillPatternDarkVertical FillPattern = 6
FillPatternDarkDown FillPattern = 7
FillPatternDarkUp FillPattern = 8
FillPatternDarkGrid FillPattern = 9
FillPatternDarkTrellis FillPattern = 10
FillPatternLightHorizontal FillPattern = 11
FillPatternLightVertical FillPattern = 12
FillPatternLightDown FillPattern = 13
FillPatternLightUp FillPattern = 14
FillPatternLightGrid FillPattern = 15
FillPatternLightTrellis FillPattern = 16
FillPatternGray125 FillPattern = 17
FillPatternGray0625 FillPattern = 18
)

func Fill(pattern FillPattern, color string) excelize.Fill {
return excelize.Fill{
Type: "pattern",
Type: string(FillTypePattern),
Pattern: int(pattern),
Color: []string{color},
}
Expand Down
Loading