diff --git a/excelizestyle/README.md b/excelizestyle/README.md
new file mode 100644
index 0000000..c3b31cd
--- /dev/null
+++ b/excelizestyle/README.md
@@ -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.
diff --git a/excelizestyle/style.go b/excelizestyle/style.go
index a75c3f0..1890d5c 100644
--- a/excelizestyle/style.go
+++ b/excelizestyle/style.go
@@ -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"
)
@@ -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),
@@ -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},
}
diff --git a/excelizestyle/style_enums_gen.go b/excelizestyle/style_enums_gen.go
new file mode 100644
index 0000000..a9fb852
--- /dev/null
+++ b/excelizestyle/style_enums_gen.go
@@ -0,0 +1,4923 @@
+// Code generated by go generate ./excelizeutil; DO NOT EDIT.
+
+package excelizestyle
+
+import "github.com/xuri/excelize/v2"
+
+// FillPattern selects the pattern index used by excelize.Fill.Pattern.
+//
+// See https://xuri.me/excelize/en/style.html
+type FillPattern int
+
+const (
+ // FillPatternNone selects the "none" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternNone FillPattern = iota
+ // FillPatternSolid selects the "solid" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternSolid
+ // FillPatternMediumGray selects the "mediumGray" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternMediumGray
+ // FillPatternDarkGray selects the "darkGray" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternDarkGray
+ // FillPatternLightGray selects the "lightGray" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternLightGray
+ // FillPatternDarkHorizontal selects the "darkHorizontal" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternDarkHorizontal
+ // FillPatternDarkVertical selects the "darkVertical" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternDarkVertical
+ // FillPatternDarkDown selects the "darkDown" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternDarkDown
+ // FillPatternDarkUp selects the "darkUp" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternDarkUp
+ // FillPatternDarkGrid selects the "darkGrid" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternDarkGrid
+ // FillPatternDarkTrellis selects the "darkTrellis" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternDarkTrellis
+ // FillPatternLightHorizontal selects the "lightHorizontal" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternLightHorizontal
+ // FillPatternLightVertical selects the "lightVertical" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternLightVertical
+ // FillPatternLightDown selects the "lightDown" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternLightDown
+ // FillPatternLightUp selects the "lightUp" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternLightUp
+ // FillPatternLightGrid selects the "lightGrid" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternLightGrid
+ // FillPatternLightTrellis selects the "lightTrellis" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternLightTrellis
+ // FillPatternGray125 selects the "gray125" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternGray125
+ // FillPatternGray0625 selects the "gray0625" cell-fill pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternGray0625
+ // FillPatternCount is the number of generated choices; it is not a valid formatting value.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillPatternCount
+)
+
+func (value FillPattern) String() string {
+ switch value {
+ case FillPatternNone:
+ return "none"
+ case FillPatternSolid:
+ return "solid"
+ case FillPatternMediumGray:
+ return "mediumGray"
+ case FillPatternDarkGray:
+ return "darkGray"
+ case FillPatternLightGray:
+ return "lightGray"
+ case FillPatternDarkHorizontal:
+ return "darkHorizontal"
+ case FillPatternDarkVertical:
+ return "darkVertical"
+ case FillPatternDarkDown:
+ return "darkDown"
+ case FillPatternDarkUp:
+ return "darkUp"
+ case FillPatternDarkGrid:
+ return "darkGrid"
+ case FillPatternDarkTrellis:
+ return "darkTrellis"
+ case FillPatternLightHorizontal:
+ return "lightHorizontal"
+ case FillPatternLightVertical:
+ return "lightVertical"
+ case FillPatternLightDown:
+ return "lightDown"
+ case FillPatternLightUp:
+ return "lightUp"
+ case FillPatternLightGrid:
+ return "lightGrid"
+ case FillPatternLightTrellis:
+ return "lightTrellis"
+ case FillPatternGray125:
+ return "gray125"
+ case FillPatternGray0625:
+ return "gray0625"
+ default:
+ return ""
+ }
+}
+
+func ParseFillPattern(value string) (FillPattern, bool) {
+ switch value {
+ case "none":
+ return FillPatternNone, true
+ case "solid":
+ return FillPatternSolid, true
+ case "mediumGray":
+ return FillPatternMediumGray, true
+ case "darkGray":
+ return FillPatternDarkGray, true
+ case "lightGray":
+ return FillPatternLightGray, true
+ case "darkHorizontal":
+ return FillPatternDarkHorizontal, true
+ case "darkVertical":
+ return FillPatternDarkVertical, true
+ case "darkDown":
+ return FillPatternDarkDown, true
+ case "darkUp":
+ return FillPatternDarkUp, true
+ case "darkGrid":
+ return FillPatternDarkGrid, true
+ case "darkTrellis":
+ return FillPatternDarkTrellis, true
+ case "lightHorizontal":
+ return FillPatternLightHorizontal, true
+ case "lightVertical":
+ return FillPatternLightVertical, true
+ case "lightDown":
+ return FillPatternLightDown, true
+ case "lightUp":
+ return FillPatternLightUp, true
+ case "lightGrid":
+ return FillPatternLightGrid, true
+ case "lightTrellis":
+ return FillPatternLightTrellis, true
+ case "gray125":
+ return FillPatternGray125, true
+ case "gray0625":
+ return FillPatternGray0625, true
+ default:
+ return 0, false
+ }
+}
+
+// BorderStyle selects the line style index used by excelize.Border.Style.
+//
+// See https://xuri.me/excelize/en/style.html
+type BorderStyle int
+
+const (
+ // BorderStyleNone selects no border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleNone BorderStyle = iota
+ // BorderStyleThin selects a thin solid border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleThin
+ // BorderStyleMedium selects a medium solid border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleMedium
+ // BorderStyleDashed selects a dashed border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleDashed
+ // BorderStyleDotted selects a dotted border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleDotted
+ // BorderStyleThick selects a thick solid border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleThick
+ // BorderStyleDouble selects a double-line border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleDouble
+ // BorderStyleHair selects a hairline border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleHair
+ // BorderStyleMediumDashed selects a medium dashed border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleMediumDashed
+ // BorderStyleDashDot selects a dash-dot border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleDashDot
+ // BorderStyleMediumDashDot selects a medium dash-dot border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleMediumDashDot
+ // BorderStyleDashDotDot selects a dash-dot-dot border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleDashDotDot
+ // BorderStyleMediumDashDotDot selects a medium dash-dot-dot border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleMediumDashDotDot
+ // BorderStyleSlantDashDot selects a slanted dash-dot border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleSlantDashDot
+ // BorderStyleCount is the number of generated choices; it is not a valid formatting value.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderStyleCount
+)
+
+func (value BorderStyle) String() string {
+ switch value {
+ case BorderStyleNone:
+ return "none"
+ case BorderStyleThin:
+ return "thin"
+ case BorderStyleMedium:
+ return "medium"
+ case BorderStyleDashed:
+ return "dashed"
+ case BorderStyleDotted:
+ return "dotted"
+ case BorderStyleThick:
+ return "thick"
+ case BorderStyleDouble:
+ return "double"
+ case BorderStyleHair:
+ return "hair"
+ case BorderStyleMediumDashed:
+ return "mediumDashed"
+ case BorderStyleDashDot:
+ return "dashDot"
+ case BorderStyleMediumDashDot:
+ return "mediumDashDot"
+ case BorderStyleDashDotDot:
+ return "dashDotDot"
+ case BorderStyleMediumDashDotDot:
+ return "mediumDashDotDot"
+ case BorderStyleSlantDashDot:
+ return "slantDashDot"
+ default:
+ return ""
+ }
+}
+
+func ParseBorderStyle(value string) (BorderStyle, bool) {
+ switch value {
+ case "none":
+ return BorderStyleNone, true
+ case "thin":
+ return BorderStyleThin, true
+ case "medium":
+ return BorderStyleMedium, true
+ case "dashed":
+ return BorderStyleDashed, true
+ case "dotted":
+ return BorderStyleDotted, true
+ case "thick":
+ return BorderStyleThick, true
+ case "double":
+ return BorderStyleDouble, true
+ case "hair":
+ return BorderStyleHair, true
+ case "mediumDashed":
+ return BorderStyleMediumDashed, true
+ case "dashDot":
+ return BorderStyleDashDot, true
+ case "mediumDashDot":
+ return BorderStyleMediumDashDot, true
+ case "dashDotDot":
+ return BorderStyleDashDotDot, true
+ case "mediumDashDotDot":
+ return BorderStyleMediumDashDotDot, true
+ case "slantDashDot":
+ return BorderStyleSlantDashDot, true
+ default:
+ return 0, false
+ }
+}
+
+// BorderPosition selects the edge or diagonal used by excelize.Border.Type.
+//
+// See https://xuri.me/excelize/en/style.html
+type BorderPosition string
+
+const (
+ // BorderPositionLeft selects the left cell edge.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderPositionLeft BorderPosition = "left"
+ // BorderPositionRight selects the right cell edge.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderPositionRight BorderPosition = "right"
+ // BorderPositionTop selects the top cell edge.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderPositionTop BorderPosition = "top"
+ // BorderPositionBottom selects the bottom cell edge.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderPositionBottom BorderPosition = "bottom"
+ // BorderPositionDiagonalUp selects the diagonal from bottom-left to top-right.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderPositionDiagonalUp BorderPosition = "diagonalUp"
+ // BorderPositionDiagonalDown selects the diagonal from top-left to bottom-right.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderPositionDiagonalDown BorderPosition = "diagonalDown"
+)
+
+func BorderPositionValues() []BorderPosition {
+ return []BorderPosition{"left", "right", "top", "bottom", "diagonalUp", "diagonalDown"}
+}
+
+// FillType selects pattern or gradient filling for excelize.Fill.Type; the empty value leaves the fill unset.
+//
+// See https://xuri.me/excelize/en/style.html
+type FillType string
+
+const (
+ // FillTypeGradient uses the selected gradient preset with two endpoint colors.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillTypeGradient FillType = "gradient"
+ // FillTypePattern uses the selected fill pattern and its foreground color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillTypePattern FillType = "pattern"
+ // FillTypeUnset leaves the formatting selector unset.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillTypeUnset FillType = ""
+)
+
+func FillTypeValues() []FillType { return []FillType{"gradient", "pattern", ""} }
+
+// AlignmentHorizontal selects horizontal cell alignment, including general alignment.
+//
+// See https://xuri.me/excelize/en/style.html
+type AlignmentHorizontal string
+
+const (
+ // AlignmentHorizontalLeft aligns text to the left edge.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentHorizontalLeft AlignmentHorizontal = "left"
+ // AlignmentHorizontalCenter centers text horizontally.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentHorizontalCenter AlignmentHorizontal = "center"
+ // AlignmentHorizontalRight aligns text to the right edge.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentHorizontalRight AlignmentHorizontal = "right"
+ // AlignmentHorizontalFill repeats the cell text across the available width.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentHorizontalFill AlignmentHorizontal = "fill"
+ // AlignmentHorizontalJustify justifies text to both horizontal edges.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentHorizontalJustify AlignmentHorizontal = "justify"
+ // AlignmentHorizontalCenterContinuous centers text across adjacent cells.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentHorizontalCenterContinuous AlignmentHorizontal = "centerContinuous"
+ // AlignmentHorizontalDistributed distributes text evenly across the available width.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentHorizontalDistributed AlignmentHorizontal = "distributed"
+ // AlignmentHorizontalGeneral aligns according to the cell value's data type.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentHorizontalGeneral AlignmentHorizontal = "general"
+)
+
+func AlignmentHorizontalValues() []AlignmentHorizontal {
+ return []AlignmentHorizontal{"left", "center", "right", "fill", "justify", "centerContinuous", "distributed", "general"}
+}
+
+// AlignmentVertical selects vertical cell alignment, including bottom alignment.
+//
+// See https://xuri.me/excelize/en/style.html
+type AlignmentVertical string
+
+const (
+ // AlignmentVerticalTop aligns text to the top edge.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentVerticalTop AlignmentVertical = "top"
+ // AlignmentVerticalCenter centers text vertically.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentVerticalCenter AlignmentVertical = "center"
+ // AlignmentVerticalJustify justifies text vertically.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentVerticalJustify AlignmentVertical = "justify"
+ // AlignmentVerticalDistributed distributes text evenly across the available height.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentVerticalDistributed AlignmentVertical = "distributed"
+ // AlignmentVerticalBottom aligns text to the bottom edge.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentVerticalBottom AlignmentVertical = "bottom"
+)
+
+func AlignmentVerticalValues() []AlignmentVertical {
+ return []AlignmentVertical{"top", "center", "justify", "distributed", "bottom"}
+}
+
+// FontUnderline selects the underline mode accepted by the selected Excelize dependency; the empty value leaves it unset.
+//
+// See https://xuri.me/excelize/en/style.html
+type FontUnderline string
+
+const (
+ // FontUnderlineNone explicitly disables underlining.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontUnderlineNone FontUnderline = "none"
+ // FontUnderlineSingle uses a single underline.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontUnderlineSingle FontUnderline = "single"
+ // FontUnderlineDouble uses a double underline.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontUnderlineDouble FontUnderline = "double"
+ // FontUnderlineUnset leaves the formatting selector unset.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontUnderlineUnset FontUnderline = ""
+)
+
+func FontUnderlineValues() []FontUnderline { return []FontUnderline{"none", "single", "double", ""} }
+
+// FontVerticalAlign selects baseline, superscript, or subscript placement of font text.
+//
+// See https://xuri.me/excelize/en/style.html
+type FontVerticalAlign string
+
+const (
+ // FontVerticalAlignBaseline uses normal baseline text.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontVerticalAlignBaseline FontVerticalAlign = "baseline"
+ // FontVerticalAlignSuperscript raises text above the baseline.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontVerticalAlignSuperscript FontVerticalAlign = "superscript"
+ // FontVerticalAlignSubscript lowers text below the baseline.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontVerticalAlignSubscript FontVerticalAlign = "subscript"
+)
+
+func FontVerticalAlignValues() []FontVerticalAlign {
+ return []FontVerticalAlign{"baseline", "superscript", "subscript"}
+}
+
+// AlignmentReadingOrder selects context-dependent, left-to-right, or right-to-left cell text direction.
+//
+// See https://xuri.me/excelize/en/style.html
+type AlignmentReadingOrder uint64
+
+const (
+ // AlignmentReadingOrderContext derives text direction from the first strong directional character.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentReadingOrderContext AlignmentReadingOrder = iota
+ // AlignmentReadingOrderLeftToRight reads cell text from left to right.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentReadingOrderLeftToRight
+ // AlignmentReadingOrderRightToLeft reads cell text from right to left.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentReadingOrderRightToLeft
+)
+
+// NumberFormat selects an Excelize number-format ID; Code and CodeForLanguage resolve the dependency's format tables, not custom workbook definitions.
+//
+// See https://xuri.me/excelize/en/style.html
+type NumberFormat int
+
+const (
+ // NumberFormatID0 selects Excelize number-format ID 0 with format code "general".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID0 NumberFormat = 0
+ // NumberFormatID1 selects Excelize number-format ID 1 with format code "0".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID1 NumberFormat = 1
+ // NumberFormatID2 selects Excelize number-format ID 2 with format code "0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID2 NumberFormat = 2
+ // NumberFormatID3 selects Excelize number-format ID 3 with format code "#,##0".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID3 NumberFormat = 3
+ // NumberFormatID4 selects Excelize number-format ID 4 with format code "#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID4 NumberFormat = 4
+ // NumberFormatID9 selects Excelize number-format ID 9 with format code "0%".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID9 NumberFormat = 9
+ // NumberFormatID10 selects Excelize number-format ID 10 with format code "0.00%".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID10 NumberFormat = 10
+ // NumberFormatID11 selects Excelize number-format ID 11 with format code "0.00E+00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID11 NumberFormat = 11
+ // NumberFormatID12 selects Excelize number-format ID 12 with format code "# ?/?".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID12 NumberFormat = 12
+ // NumberFormatID13 selects Excelize number-format ID 13 with format code "# ??/??".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID13 NumberFormat = 13
+ // NumberFormatID14 selects Excelize number-format ID 14 with format code "mm-dd-yy".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID14 NumberFormat = 14
+ // NumberFormatID15 selects Excelize number-format ID 15 with format code "d-mmm-yy".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID15 NumberFormat = 15
+ // NumberFormatID16 selects Excelize number-format ID 16 with format code "d-mmm".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID16 NumberFormat = 16
+ // NumberFormatID17 selects Excelize number-format ID 17 with format code "mmm-yy".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID17 NumberFormat = 17
+ // NumberFormatID18 selects Excelize number-format ID 18 with format code "h:mm AM/PM".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID18 NumberFormat = 18
+ // NumberFormatID19 selects Excelize number-format ID 19 with format code "h:mm:ss AM/PM".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID19 NumberFormat = 19
+ // NumberFormatID20 selects Excelize number-format ID 20 with format code "hh:mm".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID20 NumberFormat = 20
+ // NumberFormatID21 selects Excelize number-format ID 21 with format code "hh:mm:ss".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID21 NumberFormat = 21
+ // NumberFormatID22 selects Excelize number-format ID 22 with format code "m/d/yy hh:mm".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID22 NumberFormat = 22
+ // NumberFormatID27 selects Excelize number-format ID 27; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID27 NumberFormat = 27
+ // NumberFormatID28 selects Excelize number-format ID 28; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID28 NumberFormat = 28
+ // NumberFormatID29 selects Excelize number-format ID 29; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID29 NumberFormat = 29
+ // NumberFormatID30 selects Excelize number-format ID 30; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID30 NumberFormat = 30
+ // NumberFormatID31 selects Excelize number-format ID 31; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID31 NumberFormat = 31
+ // NumberFormatID32 selects Excelize number-format ID 32; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID32 NumberFormat = 32
+ // NumberFormatID33 selects Excelize number-format ID 33; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID33 NumberFormat = 33
+ // NumberFormatID34 selects Excelize number-format ID 34; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID34 NumberFormat = 34
+ // NumberFormatID35 selects Excelize number-format ID 35; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID35 NumberFormat = 35
+ // NumberFormatID36 selects Excelize number-format ID 36; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID36 NumberFormat = 36
+ // NumberFormatID37 selects Excelize number-format ID 37 with format code "#,##0 ;(#,##0)".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID37 NumberFormat = 37
+ // NumberFormatID38 selects Excelize number-format ID 38 with format code "#,##0 ;[red](#,##0)".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID38 NumberFormat = 38
+ // NumberFormatID39 selects Excelize number-format ID 39 with format code "#,##0.00 ;(#,##0.00)".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID39 NumberFormat = 39
+ // NumberFormatID40 selects Excelize number-format ID 40 with format code "#,##0.00 ;[red](#,##0.00)".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID40 NumberFormat = 40
+ // NumberFormatID41 selects Excelize number-format ID 41 with format code "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID41 NumberFormat = 41
+ // NumberFormatID42 selects Excelize number-format ID 42 with format code "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID42 NumberFormat = 42
+ // NumberFormatID43 selects Excelize number-format ID 43 with format code "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID43 NumberFormat = 43
+ // NumberFormatID44 selects Excelize number-format ID 44 with format code "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID44 NumberFormat = 44
+ // NumberFormatID45 selects Excelize number-format ID 45 with format code "mm:ss".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID45 NumberFormat = 45
+ // NumberFormatID46 selects Excelize number-format ID 46 with format code "[h]:mm:ss".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID46 NumberFormat = 46
+ // NumberFormatID47 selects Excelize number-format ID 47 with format code "mm:ss.0".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID47 NumberFormat = 47
+ // NumberFormatID48 selects Excelize number-format ID 48 with format code "##0.0E+0".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID48 NumberFormat = 48
+ // NumberFormatID49 selects Excelize number-format ID 49 with format code "@".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID49 NumberFormat = 49
+ // NumberFormatID50 selects Excelize number-format ID 50; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID50 NumberFormat = 50
+ // NumberFormatID51 selects Excelize number-format ID 51; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID51 NumberFormat = 51
+ // NumberFormatID52 selects Excelize number-format ID 52; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID52 NumberFormat = 52
+ // NumberFormatID53 selects Excelize number-format ID 53; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID53 NumberFormat = 53
+ // NumberFormatID54 selects Excelize number-format ID 54; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID54 NumberFormat = 54
+ // NumberFormatID55 selects Excelize number-format ID 55; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID55 NumberFormat = 55
+ // NumberFormatID56 selects Excelize number-format ID 56; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID56 NumberFormat = 56
+ // NumberFormatID57 selects Excelize number-format ID 57; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID57 NumberFormat = 57
+ // NumberFormatID58 selects Excelize number-format ID 58; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID58 NumberFormat = 58
+ // NumberFormatID59 selects Excelize number-format ID 59; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID59 NumberFormat = 59
+ // NumberFormatID60 selects Excelize number-format ID 60; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID60 NumberFormat = 60
+ // NumberFormatID61 selects Excelize number-format ID 61; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID61 NumberFormat = 61
+ // NumberFormatID62 selects Excelize number-format ID 62; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID62 NumberFormat = 62
+ // NumberFormatID67 selects Excelize number-format ID 67; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID67 NumberFormat = 67
+ // NumberFormatID68 selects Excelize number-format ID 68; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID68 NumberFormat = 68
+ // NumberFormatID69 selects Excelize number-format ID 69; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID69 NumberFormat = 69
+ // NumberFormatID70 selects Excelize number-format ID 70; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID70 NumberFormat = 70
+ // NumberFormatID71 selects Excelize number-format ID 71; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID71 NumberFormat = 71
+ // NumberFormatID72 selects Excelize number-format ID 72; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID72 NumberFormat = 72
+ // NumberFormatID73 selects Excelize number-format ID 73; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID73 NumberFormat = 73
+ // NumberFormatID74 selects Excelize number-format ID 74; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID74 NumberFormat = 74
+ // NumberFormatID75 selects Excelize number-format ID 75; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID75 NumberFormat = 75
+ // NumberFormatID76 selects Excelize number-format ID 76; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID76 NumberFormat = 76
+ // NumberFormatID77 selects Excelize number-format ID 77; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID77 NumberFormat = 77
+ // NumberFormatID78 selects Excelize number-format ID 78; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID78 NumberFormat = 78
+ // NumberFormatID79 selects Excelize number-format ID 79; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID79 NumberFormat = 79
+ // NumberFormatID80 selects Excelize number-format ID 80; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID80 NumberFormat = 80
+ // NumberFormatID81 selects Excelize number-format ID 81; its format depends on the language selected through CodeForLanguage.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID81 NumberFormat = 81
+ // NumberFormatID164 selects Excelize number-format ID 164 with format code "\"¥\"#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID164 NumberFormat = 164
+ // NumberFormatID165 selects Excelize number-format ID 165 with format code "[$$-409]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID165 NumberFormat = 165
+ // NumberFormatID166 selects Excelize number-format ID 166 with format code "[$$-45C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID166 NumberFormat = 166
+ // NumberFormatID167 selects Excelize number-format ID 167 with format code "[$$-1004]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID167 NumberFormat = 167
+ // NumberFormatID168 selects Excelize number-format ID 168 with format code "[$$-404]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID168 NumberFormat = 168
+ // NumberFormatID169 selects Excelize number-format ID 169 with format code "[$$-C09]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID169 NumberFormat = 169
+ // NumberFormatID170 selects Excelize number-format ID 170 with format code "[$$-2809]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID170 NumberFormat = 170
+ // NumberFormatID171 selects Excelize number-format ID 171 with format code "[$$-1009]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID171 NumberFormat = 171
+ // NumberFormatID172 selects Excelize number-format ID 172 with format code "[$$-2009]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID172 NumberFormat = 172
+ // NumberFormatID173 selects Excelize number-format ID 173 with format code "[$$-1409]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID173 NumberFormat = 173
+ // NumberFormatID174 selects Excelize number-format ID 174 with format code "[$$-4809]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID174 NumberFormat = 174
+ // NumberFormatID175 selects Excelize number-format ID 175 with format code "[$$-2C09]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID175 NumberFormat = 175
+ // NumberFormatID176 selects Excelize number-format ID 176 with format code "[$$-2409]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID176 NumberFormat = 176
+ // NumberFormatID177 selects Excelize number-format ID 177 with format code "[$$-1000]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID177 NumberFormat = 177
+ // NumberFormatID178 selects Excelize number-format ID 178 with format code "#,##0.00\\ [$$-C0C]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID178 NumberFormat = 178
+ // NumberFormatID179 selects Excelize number-format ID 179 with format code "[$$-475]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID179 NumberFormat = 179
+ // NumberFormatID180 selects Excelize number-format ID 180 with format code "[$$-83E]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID180 NumberFormat = 180
+ // NumberFormatID181 selects Excelize number-format ID 181 with format code "[$$-86B]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID181 NumberFormat = 181
+ // NumberFormatID182 selects Excelize number-format ID 182 with format code "[$$-340A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID182 NumberFormat = 182
+ // NumberFormatID183 selects Excelize number-format ID 183 with format code "[$$-240A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID183 NumberFormat = 183
+ // NumberFormatID184 selects Excelize number-format ID 184 with format code "[$$-300A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID184 NumberFormat = 184
+ // NumberFormatID185 selects Excelize number-format ID 185 with format code "[$$-440A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID185 NumberFormat = 185
+ // NumberFormatID186 selects Excelize number-format ID 186 with format code "[$$-80A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID186 NumberFormat = 186
+ // NumberFormatID187 selects Excelize number-format ID 187 with format code "[$$-500A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID187 NumberFormat = 187
+ // NumberFormatID188 selects Excelize number-format ID 188 with format code "[$$-540A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID188 NumberFormat = 188
+ // NumberFormatID189 selects Excelize number-format ID 189 with format code "[$$-380A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID189 NumberFormat = 189
+ // NumberFormatID190 selects Excelize number-format ID 190 with format code "[$£-809]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID190 NumberFormat = 190
+ // NumberFormatID191 selects Excelize number-format ID 191 with format code "[$£-491]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID191 NumberFormat = 191
+ // NumberFormatID192 selects Excelize number-format ID 192 with format code "[$£-452]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID192 NumberFormat = 192
+ // NumberFormatID193 selects Excelize number-format ID 193 with format code "[$¥-804]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID193 NumberFormat = 193
+ // NumberFormatID194 selects Excelize number-format ID 194 with format code "[$¥-411]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID194 NumberFormat = 194
+ // NumberFormatID195 selects Excelize number-format ID 195 with format code "[$¥-478]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID195 NumberFormat = 195
+ // NumberFormatID196 selects Excelize number-format ID 196 with format code "[$¥-451]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID196 NumberFormat = 196
+ // NumberFormatID197 selects Excelize number-format ID 197 with format code "[$¥-480]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID197 NumberFormat = 197
+ // NumberFormatID198 selects Excelize number-format ID 198 with format code "#,##0.00\\ [$֏-42B]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID198 NumberFormat = 198
+ // NumberFormatID199 selects Excelize number-format ID 199 with format code "[$؋-463]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID199 NumberFormat = 199
+ // NumberFormatID200 selects Excelize number-format ID 200 with format code "[$؋-48C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID200 NumberFormat = 200
+ // NumberFormatID201 selects Excelize number-format ID 201 with format code "[$৳-845]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID201 NumberFormat = 201
+ // NumberFormatID202 selects Excelize number-format ID 202 with format code "#,##0.00[$៛-453]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID202 NumberFormat = 202
+ // NumberFormatID203 selects Excelize number-format ID 203 with format code "[$₡-140A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID203 NumberFormat = 203
+ // NumberFormatID204 selects Excelize number-format ID 204 with format code "[$₦-468]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID204 NumberFormat = 204
+ // NumberFormatID205 selects Excelize number-format ID 205 with format code "[$₦-470]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID205 NumberFormat = 205
+ // NumberFormatID206 selects Excelize number-format ID 206 with format code "[$₩-412]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID206 NumberFormat = 206
+ // NumberFormatID207 selects Excelize number-format ID 207 with format code "[$₪-40D]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID207 NumberFormat = 207
+ // NumberFormatID208 selects Excelize number-format ID 208 with format code "#,##0.00\\ [$₫-42A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID208 NumberFormat = 208
+ // NumberFormatID209 selects Excelize number-format ID 209 with format code "#,##0.00\\ [$€-42D]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID209 NumberFormat = 209
+ // NumberFormatID210 selects Excelize number-format ID 210 with format code "#,##0.00\\ [$€-47E]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID210 NumberFormat = 210
+ // NumberFormatID211 selects Excelize number-format ID 211 with format code "#,##0.00\\ [$€-403]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID211 NumberFormat = 211
+ // NumberFormatID212 selects Excelize number-format ID 212 with format code "#,##0.00\\ [$€-483]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID212 NumberFormat = 212
+ // NumberFormatID213 selects Excelize number-format ID 213 with format code "[$€-813]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID213 NumberFormat = 213
+ // NumberFormatID214 selects Excelize number-format ID 214 with format code "[$€-413]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID214 NumberFormat = 214
+ // NumberFormatID215 selects Excelize number-format ID 215 with format code "[$€-1809]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID215 NumberFormat = 215
+ // NumberFormatID216 selects Excelize number-format ID 216 with format code "#,##0.00\\ [$€-425]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID216 NumberFormat = 216
+ // NumberFormatID217 selects Excelize number-format ID 217 with format code "[$€-2]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID217 NumberFormat = 217
+ // NumberFormatID218 selects Excelize number-format ID 218 with format code "#,##0.00\\ [$€-1]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID218 NumberFormat = 218
+ // NumberFormatID219 selects Excelize number-format ID 219 with format code "#,##0.00\\ [$€-40B]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID219 NumberFormat = 219
+ // NumberFormatID220 selects Excelize number-format ID 220 with format code "#,##0.00\\ [$€-80C]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID220 NumberFormat = 220
+ // NumberFormatID221 selects Excelize number-format ID 221 with format code "#,##0.00\\ [$€-40C]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID221 NumberFormat = 221
+ // NumberFormatID222 selects Excelize number-format ID 222 with format code "#,##0.00\\ [$€-140C]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID222 NumberFormat = 222
+ // NumberFormatID223 selects Excelize number-format ID 223 with format code "#,##0.00\\ [$€-180C]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID223 NumberFormat = 223
+ // NumberFormatID224 selects Excelize number-format ID 224 with format code "[$€-200C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID224 NumberFormat = 224
+ // NumberFormatID225 selects Excelize number-format ID 225 with format code "#,##0.00\\ [$€-456]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID225 NumberFormat = 225
+ // NumberFormatID226 selects Excelize number-format ID 226 with format code "#,##0.00\\ [$€-C07]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID226 NumberFormat = 226
+ // NumberFormatID227 selects Excelize number-format ID 227 with format code "#,##0.00\\ [$€-407]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID227 NumberFormat = 227
+ // NumberFormatID228 selects Excelize number-format ID 228 with format code "#,##0.00\\ [$€-1007]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID228 NumberFormat = 228
+ // NumberFormatID229 selects Excelize number-format ID 229 with format code "#,##0.00\\ [$€-408]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID229 NumberFormat = 229
+ // NumberFormatID230 selects Excelize number-format ID 230 with format code "#,##0.00\\ [$€-243B]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID230 NumberFormat = 230
+ // NumberFormatID231 selects Excelize number-format ID 231 with format code "[$€-83C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID231 NumberFormat = 231
+ // NumberFormatID232 selects Excelize number-format ID 232 with format code "[$€-410]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID232 NumberFormat = 232
+ // NumberFormatID233 selects Excelize number-format ID 233 with format code "[$€-476]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID233 NumberFormat = 233
+ // NumberFormatID234 selects Excelize number-format ID 234 with format code "#,##0.00\\ [$€-2C1A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID234 NumberFormat = 234
+ // NumberFormatID235 selects Excelize number-format ID 235 with format code "[$€-426]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID235 NumberFormat = 235
+ // NumberFormatID236 selects Excelize number-format ID 236 with format code "#,##0.00\\ [$€-427]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID236 NumberFormat = 236
+ // NumberFormatID237 selects Excelize number-format ID 237 with format code "#,##0.00\\ [$€-82E]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID237 NumberFormat = 237
+ // NumberFormatID238 selects Excelize number-format ID 238 with format code "#,##0.00\\ [$€-46E]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID238 NumberFormat = 238
+ // NumberFormatID239 selects Excelize number-format ID 239 with format code "[$€-43A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID239 NumberFormat = 239
+ // NumberFormatID240 selects Excelize number-format ID 240 with format code "#,##0.00\\ [$€-C3B]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID240 NumberFormat = 240
+ // NumberFormatID241 selects Excelize number-format ID 241 with format code "#,##0.00\\ [$€-482]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID241 NumberFormat = 241
+ // NumberFormatID242 selects Excelize number-format ID 242 with format code "#,##0.00\\ [$€-816]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID242 NumberFormat = 242
+ // NumberFormatID243 selects Excelize number-format ID 243 with format code "#,##0.00\\ [$€-301A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID243 NumberFormat = 243
+ // NumberFormatID244 selects Excelize number-format ID 244 with format code "#,##0.00\\ [$€-203B]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID244 NumberFormat = 244
+ // NumberFormatID245 selects Excelize number-format ID 245 with format code "#,##0.00\\ [$€-41B]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID245 NumberFormat = 245
+ // NumberFormatID246 selects Excelize number-format ID 246 with format code "#,##0.00\\ [$€-424]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID246 NumberFormat = 246
+ // NumberFormatID247 selects Excelize number-format ID 247 with format code "#,##0.00\\ [$€-C0A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID247 NumberFormat = 247
+ // NumberFormatID248 selects Excelize number-format ID 248 with format code "#,##0.00\\ [$€-81D]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID248 NumberFormat = 248
+ // NumberFormatID249 selects Excelize number-format ID 249 with format code "#,##0.00\\ [$€-484]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID249 NumberFormat = 249
+ // NumberFormatID250 selects Excelize number-format ID 250 with format code "#,##0.00\\ [$€-42E]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID250 NumberFormat = 250
+ // NumberFormatID251 selects Excelize number-format ID 251 with format code "[$€-462]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID251 NumberFormat = 251
+ // NumberFormatID252 selects Excelize number-format ID 252 with format code "#,##0.00\\ [$₭-454]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID252 NumberFormat = 252
+ // NumberFormatID253 selects Excelize number-format ID 253 with format code "#,##0.00\\ [$₮-450]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID253 NumberFormat = 253
+ // NumberFormatID254 selects Excelize number-format ID 254 with format code "[$₮-C50]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID254 NumberFormat = 254
+ // NumberFormatID255 selects Excelize number-format ID 255 with format code "[$₱-3409]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID255 NumberFormat = 255
+ // NumberFormatID256 selects Excelize number-format ID 256 with format code "[$₱-464]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID256 NumberFormat = 256
+ // NumberFormatID257 selects Excelize number-format ID 257 with format code "#,##0.00[$₴-422]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID257 NumberFormat = 257
+ // NumberFormatID258 selects Excelize number-format ID 258 with format code "[$₸-43F]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID258 NumberFormat = 258
+ // NumberFormatID259 selects Excelize number-format ID 259 with format code "[$₹-460]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID259 NumberFormat = 259
+ // NumberFormatID260 selects Excelize number-format ID 260 with format code "[$₹-4009]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID260 NumberFormat = 260
+ // NumberFormatID261 selects Excelize number-format ID 261 with format code "[$₹-447]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID261 NumberFormat = 261
+ // NumberFormatID262 selects Excelize number-format ID 262 with format code "[$₹-439]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID262 NumberFormat = 262
+ // NumberFormatID263 selects Excelize number-format ID 263 with format code "[$₹-44B]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID263 NumberFormat = 263
+ // NumberFormatID264 selects Excelize number-format ID 264 with format code "[$₹-860]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID264 NumberFormat = 264
+ // NumberFormatID265 selects Excelize number-format ID 265 with format code "[$₹-457]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID265 NumberFormat = 265
+ // NumberFormatID266 selects Excelize number-format ID 266 with format code "[$₹-458]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID266 NumberFormat = 266
+ // NumberFormatID267 selects Excelize number-format ID 267 with format code "[$₹-44E]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID267 NumberFormat = 267
+ // NumberFormatID268 selects Excelize number-format ID 268 with format code "[$₹-861]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID268 NumberFormat = 268
+ // NumberFormatID269 selects Excelize number-format ID 269 with format code "[$₹-448]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID269 NumberFormat = 269
+ // NumberFormatID270 selects Excelize number-format ID 270 with format code "[$₹-446]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID270 NumberFormat = 270
+ // NumberFormatID271 selects Excelize number-format ID 271 with format code "[$₹-44F]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID271 NumberFormat = 271
+ // NumberFormatID272 selects Excelize number-format ID 272 with format code "[$₹-459]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID272 NumberFormat = 272
+ // NumberFormatID273 selects Excelize number-format ID 273 with format code "[$₹-449]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID273 NumberFormat = 273
+ // NumberFormatID274 selects Excelize number-format ID 274 with format code "[$₹-820]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID274 NumberFormat = 274
+ // NumberFormatID275 selects Excelize number-format ID 275 with format code "#,##0.00\\ [$₺-41F]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID275 NumberFormat = 275
+ // NumberFormatID276 selects Excelize number-format ID 276 with format code "#,##0.00\\ [$₼-42C]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID276 NumberFormat = 276
+ // NumberFormatID277 selects Excelize number-format ID 277 with format code "#,##0.00\\ [$₼-82C]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID277 NumberFormat = 277
+ // NumberFormatID278 selects Excelize number-format ID 278 with format code "#,##0.00\\ [$₽-419]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID278 NumberFormat = 278
+ // NumberFormatID279 selects Excelize number-format ID 279 with format code "#,##0.00[$₽-485]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID279 NumberFormat = 279
+ // NumberFormatID280 selects Excelize number-format ID 280 with format code "#,##0.00\\ [$₾-437]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID280 NumberFormat = 280
+ // NumberFormatID281 selects Excelize number-format ID 281 with format code "[$B/.-180A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID281 NumberFormat = 281
+ // NumberFormatID282 selects Excelize number-format ID 282 with format code "[$Br-472]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID282 NumberFormat = 282
+ // NumberFormatID283 selects Excelize number-format ID 283 with format code "[$Br-477]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID283 NumberFormat = 283
+ // NumberFormatID284 selects Excelize number-format ID 284 with format code "#,##0.00[$Br-473]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID284 NumberFormat = 284
+ // NumberFormatID285 selects Excelize number-format ID 285 with format code "[$Bs-46B]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID285 NumberFormat = 285
+ // NumberFormatID286 selects Excelize number-format ID 286 with format code "[$Bs-400A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID286 NumberFormat = 286
+ // NumberFormatID287 selects Excelize number-format ID 287 with format code "[$Bs.-200A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID287 NumberFormat = 287
+ // NumberFormatID288 selects Excelize number-format ID 288 with format code "[$BWP-832]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID288 NumberFormat = 288
+ // NumberFormatID289 selects Excelize number-format ID 289 with format code "[$C$-4C0A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID289 NumberFormat = 289
+ // NumberFormatID290 selects Excelize number-format ID 290 with format code "[$CA$-85D]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID290 NumberFormat = 290
+ // NumberFormatID291 selects Excelize number-format ID 291 with format code "[$CA$-47C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID291 NumberFormat = 291
+ // NumberFormatID292 selects Excelize number-format ID 292 with format code "[$CA$-45D]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID292 NumberFormat = 292
+ // NumberFormatID293 selects Excelize number-format ID 293 with format code "[$CFA-340C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID293 NumberFormat = 293
+ // NumberFormatID294 selects Excelize number-format ID 294 with format code "[$CFA-280C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID294 NumberFormat = 294
+ // NumberFormatID295 selects Excelize number-format ID 295 with format code "#,##0.00\\ [$CFA-867]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID295 NumberFormat = 295
+ // NumberFormatID296 selects Excelize number-format ID 296 with format code "#,##0.00\\ [$CFA-488]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID296 NumberFormat = 296
+ // NumberFormatID297 selects Excelize number-format ID 297 with format code "#,##0.00\\ [$CHF-100C]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID297 NumberFormat = 297
+ // NumberFormatID298 selects Excelize number-format ID 298 with format code "[$CHF-1407]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID298 NumberFormat = 298
+ // NumberFormatID299 selects Excelize number-format ID 299 with format code "[$CHF-807]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID299 NumberFormat = 299
+ // NumberFormatID300 selects Excelize number-format ID 300 with format code "[$CHF-810]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID300 NumberFormat = 300
+ // NumberFormatID301 selects Excelize number-format ID 301 with format code "[$CHF-417]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID301 NumberFormat = 301
+ // NumberFormatID302 selects Excelize number-format ID 302 with format code "[$CLP-47A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID302 NumberFormat = 302
+ // NumberFormatID303 selects Excelize number-format ID 303 with format code "[$CN¥-850]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID303 NumberFormat = 303
+ // NumberFormatID304 selects Excelize number-format ID 304 with format code "#,##0.00\\ [$DZD-85F]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID304 NumberFormat = 304
+ // NumberFormatID305 selects Excelize number-format ID 305 with format code "[$FCFA-2C0C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID305 NumberFormat = 305
+ // NumberFormatID306 selects Excelize number-format ID 306 with format code "#,##0.00\\ [$Ft-40E]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID306 NumberFormat = 306
+ // NumberFormatID307 selects Excelize number-format ID 307 with format code "[$G-3C0C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID307 NumberFormat = 307
+ // NumberFormatID308 selects Excelize number-format ID 308 with format code "[$Gs.-3C0A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID308 NumberFormat = 308
+ // NumberFormatID309 selects Excelize number-format ID 309 with format code "[$GTQ-486]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID309 NumberFormat = 309
+ // NumberFormatID310 selects Excelize number-format ID 310 with format code "[$HK$-C04]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID310 NumberFormat = 310
+ // NumberFormatID311 selects Excelize number-format ID 311 with format code "[$HK$-3C09]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID311 NumberFormat = 311
+ // NumberFormatID312 selects Excelize number-format ID 312 with format code "#,##0.00\\ [$HRK-41A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID312 NumberFormat = 312
+ // NumberFormatID313 selects Excelize number-format ID 313 with format code "[$IDR-3809]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID313 NumberFormat = 313
+ // NumberFormatID314 selects Excelize number-format ID 314 with format code "[$IQD-492]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID314 NumberFormat = 314
+ // NumberFormatID315 selects Excelize number-format ID 315 with format code "#,##0.00\\ [$ISK-40F]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID315 NumberFormat = 315
+ // NumberFormatID316 selects Excelize number-format ID 316 with format code "[$K-455]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID316 NumberFormat = 316
+ // NumberFormatID317 selects Excelize number-format ID 317 with format code "#,##0.00\\ [$Kč-405]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID317 NumberFormat = 317
+ // NumberFormatID318 selects Excelize number-format ID 318 with format code "#,##0.00\\ [$KM-141A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID318 NumberFormat = 318
+ // NumberFormatID319 selects Excelize number-format ID 319 with format code "#,##0.00\\ [$KM-101A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID319 NumberFormat = 319
+ // NumberFormatID320 selects Excelize number-format ID 320 with format code "#,##0.00\\ [$KM-181A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID320 NumberFormat = 320
+ // NumberFormatID321 selects Excelize number-format ID 321 with format code "[$kr-438]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID321 NumberFormat = 321
+ // NumberFormatID322 selects Excelize number-format ID 322 with format code "[$kr-43B]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID322 NumberFormat = 322
+ // NumberFormatID323 selects Excelize number-format ID 323 with format code "#,##0.00\\ [$kr-83B]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID323 NumberFormat = 323
+ // NumberFormatID324 selects Excelize number-format ID 324 with format code "[$kr-414]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID324 NumberFormat = 324
+ // NumberFormatID325 selects Excelize number-format ID 325 with format code "[$kr-814]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID325 NumberFormat = 325
+ // NumberFormatID326 selects Excelize number-format ID 326 with format code "#,##0.00\\ [$kr-41D]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID326 NumberFormat = 326
+ // NumberFormatID327 selects Excelize number-format ID 327 with format code "[$kr.-406]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID327 NumberFormat = 327
+ // NumberFormatID328 selects Excelize number-format ID 328 with format code "[$kr.-46F]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID328 NumberFormat = 328
+ // NumberFormatID329 selects Excelize number-format ID 329 with format code "[$Ksh-441]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID329 NumberFormat = 329
+ // NumberFormatID330 selects Excelize number-format ID 330 with format code "[$L-818]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID330 NumberFormat = 330
+ // NumberFormatID331 selects Excelize number-format ID 331 with format code "[$L-819]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID331 NumberFormat = 331
+ // NumberFormatID332 selects Excelize number-format ID 332 with format code "[$L-480A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID332 NumberFormat = 332
+ // NumberFormatID333 selects Excelize number-format ID 333 with format code "#,##0.00\\ [$Lekë-41C]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID333 NumberFormat = 333
+ // NumberFormatID334 selects Excelize number-format ID 334 with format code "[$MAD-45F]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID334 NumberFormat = 334
+ // NumberFormatID335 selects Excelize number-format ID 335 with format code "[$MAD-380C]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID335 NumberFormat = 335
+ // NumberFormatID336 selects Excelize number-format ID 336 with format code "#,##0.00\\ [$MAD-105F]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID336 NumberFormat = 336
+ // NumberFormatID337 selects Excelize number-format ID 337 with format code "[$MOP$-1404]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID337 NumberFormat = 337
+ // NumberFormatID338 selects Excelize number-format ID 338 with format code "#,##0.00\\ [$MVR-465]_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID338 NumberFormat = 338
+ // NumberFormatID339 selects Excelize number-format ID 339 with format code "#,##0.00[$Nfk-873]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID339 NumberFormat = 339
+ // NumberFormatID340 selects Excelize number-format ID 340 with format code "[$NGN-466]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID340 NumberFormat = 340
+ // NumberFormatID341 selects Excelize number-format ID 341 with format code "[$NGN-467]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID341 NumberFormat = 341
+ // NumberFormatID342 selects Excelize number-format ID 342 with format code "[$NGN-469]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID342 NumberFormat = 342
+ // NumberFormatID343 selects Excelize number-format ID 343 with format code "[$NGN-471]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID343 NumberFormat = 343
+ // NumberFormatID344 selects Excelize number-format ID 344 with format code "[$NOK-103B]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID344 NumberFormat = 344
+ // NumberFormatID345 selects Excelize number-format ID 345 with format code "[$NOK-183B]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID345 NumberFormat = 345
+ // NumberFormatID346 selects Excelize number-format ID 346 with format code "[$NZ$-481]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID346 NumberFormat = 346
+ // NumberFormatID347 selects Excelize number-format ID 347 with format code "[$PKR-859]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID347 NumberFormat = 347
+ // NumberFormatID348 selects Excelize number-format ID 348 with format code "[$PYG-474]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID348 NumberFormat = 348
+ // NumberFormatID349 selects Excelize number-format ID 349 with format code "[$Q-100A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID349 NumberFormat = 349
+ // NumberFormatID350 selects Excelize number-format ID 350 with format code "[$R-436]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID350 NumberFormat = 350
+ // NumberFormatID351 selects Excelize number-format ID 351 with format code "[$R-1C09]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID351 NumberFormat = 351
+ // NumberFormatID352 selects Excelize number-format ID 352 with format code "[$R-435]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID352 NumberFormat = 352
+ // NumberFormatID353 selects Excelize number-format ID 353 with format code "[$R$-416]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID353 NumberFormat = 353
+ // NumberFormatID354 selects Excelize number-format ID 354 with format code "[$RD$-1C0A]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID354 NumberFormat = 354
+ // NumberFormatID355 selects Excelize number-format ID 355 with format code "#,##0.00\\ [$RF-487]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID355 NumberFormat = 355
+ // NumberFormatID356 selects Excelize number-format ID 356 with format code "[$RM-4409]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID356 NumberFormat = 356
+ // NumberFormatID357 selects Excelize number-format ID 357 with format code "[$RM-43E]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID357 NumberFormat = 357
+ // NumberFormatID358 selects Excelize number-format ID 358 with format code "#,##0.00\\ [$RON-418]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID358 NumberFormat = 358
+ // NumberFormatID359 selects Excelize number-format ID 359 with format code "[$Rp-421]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID359 NumberFormat = 359
+ // NumberFormatID360 selects Excelize number-format ID 360 with format code "[$Rs-420]#,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID360 NumberFormat = 360
+ // NumberFormatID361 selects Excelize number-format ID 361 with format code "[$Rs.-849]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID361 NumberFormat = 361
+ // NumberFormatID362 selects Excelize number-format ID 362 with format code "#,##0.00\\ [$RSD-81A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID362 NumberFormat = 362
+ // NumberFormatID363 selects Excelize number-format ID 363 with format code "#,##0.00\\ [$RSD-C1A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID363 NumberFormat = 363
+ // NumberFormatID364 selects Excelize number-format ID 364 with format code "#,##0.00\\ [$RUB-46D]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID364 NumberFormat = 364
+ // NumberFormatID365 selects Excelize number-format ID 365 with format code "#,##0.00\\ [$RUB-444]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID365 NumberFormat = 365
+ // NumberFormatID366 selects Excelize number-format ID 366 with format code "[$S/.-C6B]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID366 NumberFormat = 366
+ // NumberFormatID367 selects Excelize number-format ID 367 with format code "[$S/.-280A]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID367 NumberFormat = 367
+ // NumberFormatID368 selects Excelize number-format ID 368 with format code "#,##0.00\\ [$SEK-143B]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID368 NumberFormat = 368
+ // NumberFormatID369 selects Excelize number-format ID 369 with format code "#,##0.00\\ [$SEK-1C3B]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID369 NumberFormat = 369
+ // NumberFormatID370 selects Excelize number-format ID 370 with format code "#,##0.00\\ [$soʻm-443]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID370 NumberFormat = 370
+ // NumberFormatID371 selects Excelize number-format ID 371 with format code "#,##0.00\\ [$soʻm-843]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID371 NumberFormat = 371
+ // NumberFormatID372 selects Excelize number-format ID 372 with format code "#,##0.00\\ [$SYP-45A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID372 NumberFormat = 372
+ // NumberFormatID373 selects Excelize number-format ID 373 with format code "[$THB-41E]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID373 NumberFormat = 373
+ // NumberFormatID374 selects Excelize number-format ID 374 with format code "#,##0.00[$TMT-442]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID374 NumberFormat = 374
+ // NumberFormatID375 selects Excelize number-format ID 375 with format code "[$US$-3009]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID375 NumberFormat = 375
+ // NumberFormatID376 selects Excelize number-format ID 376 with format code "[$ZAR-46C]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID376 NumberFormat = 376
+ // NumberFormatID377 selects Excelize number-format ID 377 with format code "[$ZAR-430]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID377 NumberFormat = 377
+ // NumberFormatID378 selects Excelize number-format ID 378 with format code "[$ZAR-431]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID378 NumberFormat = 378
+ // NumberFormatID379 selects Excelize number-format ID 379 with format code "[$ZAR-432]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID379 NumberFormat = 379
+ // NumberFormatID380 selects Excelize number-format ID 380 with format code "[$ZAR-433]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID380 NumberFormat = 380
+ // NumberFormatID381 selects Excelize number-format ID 381 with format code "[$ZAR-434]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID381 NumberFormat = 381
+ // NumberFormatID382 selects Excelize number-format ID 382 with format code "#,##0.00\\ [$zł-415]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID382 NumberFormat = 382
+ // NumberFormatID383 selects Excelize number-format ID 383 with format code "#,##0.00\\ [$ден-42F]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID383 NumberFormat = 383
+ // NumberFormatID384 selects Excelize number-format ID 384 with format code "#,##0.00\\ [$КМ-201A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID384 NumberFormat = 384
+ // NumberFormatID385 selects Excelize number-format ID 385 with format code "#,##0.00\\ [$КМ-1C1A]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID385 NumberFormat = 385
+ // NumberFormatID386 selects Excelize number-format ID 386 with format code "#,##0.00\\ [$лв.-402]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID386 NumberFormat = 386
+ // NumberFormatID387 selects Excelize number-format ID 387 with format code "#,##0.00\\ [$р.-423]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID387 NumberFormat = 387
+ // NumberFormatID388 selects Excelize number-format ID 388 with format code "#,##0.00\\ [$сом-440]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID388 NumberFormat = 388
+ // NumberFormatID389 selects Excelize number-format ID 389 with format code "#,##0.00\\ [$сом-428]".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID389 NumberFormat = 389
+ // NumberFormatID390 selects Excelize number-format ID 390 with format code "[$ج.م.-C01]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID390 NumberFormat = 390
+ // NumberFormatID391 selects Excelize number-format ID 391 with format code "[$د.أ.-2C01]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID391 NumberFormat = 391
+ // NumberFormatID392 selects Excelize number-format ID 392 with format code "[$د.إ.-3801]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID392 NumberFormat = 392
+ // NumberFormatID393 selects Excelize number-format ID 393 with format code "[$د.ب.-3C01]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID393 NumberFormat = 393
+ // NumberFormatID394 selects Excelize number-format ID 394 with format code "[$د.ت.-1C01]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID394 NumberFormat = 394
+ // NumberFormatID395 selects Excelize number-format ID 395 with format code "[$د.ج.-1401]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID395 NumberFormat = 395
+ // NumberFormatID396 selects Excelize number-format ID 396 with format code "[$د.ع.-801]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID396 NumberFormat = 396
+ // NumberFormatID397 selects Excelize number-format ID 397 with format code "[$د.ك.-3401]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID397 NumberFormat = 397
+ // NumberFormatID398 selects Excelize number-format ID 398 with format code "[$د.ل.-1001]#,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID398 NumberFormat = 398
+ // NumberFormatID399 selects Excelize number-format ID 399 with format code "[$د.م.-1801]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID399 NumberFormat = 399
+ // NumberFormatID400 selects Excelize number-format ID 400 with format code "[$ر-846]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID400 NumberFormat = 400
+ // NumberFormatID401 selects Excelize number-format ID 401 with format code "[$ر.س.-401]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID401 NumberFormat = 401
+ // NumberFormatID402 selects Excelize number-format ID 402 with format code "[$ر.ع.-2001]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID402 NumberFormat = 402
+ // NumberFormatID403 selects Excelize number-format ID 403 with format code "[$ر.ق.-4001]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID403 NumberFormat = 403
+ // NumberFormatID404 selects Excelize number-format ID 404 with format code "[$ر.ي.-2401]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID404 NumberFormat = 404
+ // NumberFormatID405 selects Excelize number-format ID 405 with format code "[$ریال-429]#,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID405 NumberFormat = 405
+ // NumberFormatID406 selects Excelize number-format ID 406 with format code "[$ل.س.-2801]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID406 NumberFormat = 406
+ // NumberFormatID407 selects Excelize number-format ID 407 with format code "[$ل.ل.-3001]\\ #,##0.00_-".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID407 NumberFormat = 407
+ // NumberFormatID408 selects Excelize number-format ID 408 with format code "[$ብር-45E]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID408 NumberFormat = 408
+ // NumberFormatID409 selects Excelize number-format ID 409 with format code "[$रू-461]#,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID409 NumberFormat = 409
+ // NumberFormatID410 selects Excelize number-format ID 410 with format code "[$රු.-45B]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID410 NumberFormat = 410
+ // NumberFormatID411 selects Excelize number-format ID 411 with format code "[$ADP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID411 NumberFormat = 411
+ // NumberFormatID412 selects Excelize number-format ID 412 with format code "[$AED]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID412 NumberFormat = 412
+ // NumberFormatID413 selects Excelize number-format ID 413 with format code "[$AFA]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID413 NumberFormat = 413
+ // NumberFormatID414 selects Excelize number-format ID 414 with format code "[$AFN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID414 NumberFormat = 414
+ // NumberFormatID415 selects Excelize number-format ID 415 with format code "[$ALL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID415 NumberFormat = 415
+ // NumberFormatID416 selects Excelize number-format ID 416 with format code "[$AMD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID416 NumberFormat = 416
+ // NumberFormatID417 selects Excelize number-format ID 417 with format code "[$ANG]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID417 NumberFormat = 417
+ // NumberFormatID418 selects Excelize number-format ID 418 with format code "[$AOA]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID418 NumberFormat = 418
+ // NumberFormatID419 selects Excelize number-format ID 419 with format code "[$ARS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID419 NumberFormat = 419
+ // NumberFormatID420 selects Excelize number-format ID 420 with format code "[$ATS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID420 NumberFormat = 420
+ // NumberFormatID421 selects Excelize number-format ID 421 with format code "[$AUD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID421 NumberFormat = 421
+ // NumberFormatID422 selects Excelize number-format ID 422 with format code "[$AWG]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID422 NumberFormat = 422
+ // NumberFormatID423 selects Excelize number-format ID 423 with format code "[$AZM]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID423 NumberFormat = 423
+ // NumberFormatID424 selects Excelize number-format ID 424 with format code "[$AZN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID424 NumberFormat = 424
+ // NumberFormatID425 selects Excelize number-format ID 425 with format code "[$BAM]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID425 NumberFormat = 425
+ // NumberFormatID426 selects Excelize number-format ID 426 with format code "[$BBD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID426 NumberFormat = 426
+ // NumberFormatID427 selects Excelize number-format ID 427 with format code "[$BDT]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID427 NumberFormat = 427
+ // NumberFormatID428 selects Excelize number-format ID 428 with format code "[$BEF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID428 NumberFormat = 428
+ // NumberFormatID429 selects Excelize number-format ID 429 with format code "[$BGL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID429 NumberFormat = 429
+ // NumberFormatID430 selects Excelize number-format ID 430 with format code "[$BGN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID430 NumberFormat = 430
+ // NumberFormatID431 selects Excelize number-format ID 431 with format code "[$BHD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID431 NumberFormat = 431
+ // NumberFormatID432 selects Excelize number-format ID 432 with format code "[$BIF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID432 NumberFormat = 432
+ // NumberFormatID433 selects Excelize number-format ID 433 with format code "[$BMD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID433 NumberFormat = 433
+ // NumberFormatID434 selects Excelize number-format ID 434 with format code "[$BND]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID434 NumberFormat = 434
+ // NumberFormatID435 selects Excelize number-format ID 435 with format code "[$BOB]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID435 NumberFormat = 435
+ // NumberFormatID436 selects Excelize number-format ID 436 with format code "[$BOV]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID436 NumberFormat = 436
+ // NumberFormatID437 selects Excelize number-format ID 437 with format code "[$BRL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID437 NumberFormat = 437
+ // NumberFormatID438 selects Excelize number-format ID 438 with format code "[$BSD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID438 NumberFormat = 438
+ // NumberFormatID439 selects Excelize number-format ID 439 with format code "[$BTN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID439 NumberFormat = 439
+ // NumberFormatID440 selects Excelize number-format ID 440 with format code "[$BWP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID440 NumberFormat = 440
+ // NumberFormatID441 selects Excelize number-format ID 441 with format code "[$BYR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID441 NumberFormat = 441
+ // NumberFormatID442 selects Excelize number-format ID 442 with format code "[$BZD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID442 NumberFormat = 442
+ // NumberFormatID443 selects Excelize number-format ID 443 with format code "[$CAD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID443 NumberFormat = 443
+ // NumberFormatID444 selects Excelize number-format ID 444 with format code "[$CDF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID444 NumberFormat = 444
+ // NumberFormatID445 selects Excelize number-format ID 445 with format code "[$CHE]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID445 NumberFormat = 445
+ // NumberFormatID446 selects Excelize number-format ID 446 with format code "[$CHF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID446 NumberFormat = 446
+ // NumberFormatID447 selects Excelize number-format ID 447 with format code "[$CHW]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID447 NumberFormat = 447
+ // NumberFormatID448 selects Excelize number-format ID 448 with format code "[$CLF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID448 NumberFormat = 448
+ // NumberFormatID449 selects Excelize number-format ID 449 with format code "[$CLP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID449 NumberFormat = 449
+ // NumberFormatID450 selects Excelize number-format ID 450 with format code "[$CNY]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID450 NumberFormat = 450
+ // NumberFormatID451 selects Excelize number-format ID 451 with format code "[$COP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID451 NumberFormat = 451
+ // NumberFormatID452 selects Excelize number-format ID 452 with format code "[$COU]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID452 NumberFormat = 452
+ // NumberFormatID453 selects Excelize number-format ID 453 with format code "[$CRC]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID453 NumberFormat = 453
+ // NumberFormatID454 selects Excelize number-format ID 454 with format code "[$CSD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID454 NumberFormat = 454
+ // NumberFormatID455 selects Excelize number-format ID 455 with format code "[$CUC]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID455 NumberFormat = 455
+ // NumberFormatID456 selects Excelize number-format ID 456 with format code "[$CVE]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID456 NumberFormat = 456
+ // NumberFormatID457 selects Excelize number-format ID 457 with format code "[$CYP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID457 NumberFormat = 457
+ // NumberFormatID458 selects Excelize number-format ID 458 with format code "[$CZK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID458 NumberFormat = 458
+ // NumberFormatID459 selects Excelize number-format ID 459 with format code "[$DEM]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID459 NumberFormat = 459
+ // NumberFormatID460 selects Excelize number-format ID 460 with format code "[$DJF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID460 NumberFormat = 460
+ // NumberFormatID461 selects Excelize number-format ID 461 with format code "[$DKK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID461 NumberFormat = 461
+ // NumberFormatID462 selects Excelize number-format ID 462 with format code "[$DOP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID462 NumberFormat = 462
+ // NumberFormatID463 selects Excelize number-format ID 463 with format code "[$DZD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID463 NumberFormat = 463
+ // NumberFormatID464 selects Excelize number-format ID 464 with format code "[$ECS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID464 NumberFormat = 464
+ // NumberFormatID465 selects Excelize number-format ID 465 with format code "[$ECV]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID465 NumberFormat = 465
+ // NumberFormatID466 selects Excelize number-format ID 466 with format code "[$EEK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID466 NumberFormat = 466
+ // NumberFormatID467 selects Excelize number-format ID 467 with format code "[$EGP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID467 NumberFormat = 467
+ // NumberFormatID468 selects Excelize number-format ID 468 with format code "[$ERN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID468 NumberFormat = 468
+ // NumberFormatID469 selects Excelize number-format ID 469 with format code "[$ESP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID469 NumberFormat = 469
+ // NumberFormatID470 selects Excelize number-format ID 470 with format code "[$ETB]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID470 NumberFormat = 470
+ // NumberFormatID471 selects Excelize number-format ID 471 with format code "[$EUR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID471 NumberFormat = 471
+ // NumberFormatID472 selects Excelize number-format ID 472 with format code "[$FIM]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID472 NumberFormat = 472
+ // NumberFormatID473 selects Excelize number-format ID 473 with format code "[$FJD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID473 NumberFormat = 473
+ // NumberFormatID474 selects Excelize number-format ID 474 with format code "[$FKP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID474 NumberFormat = 474
+ // NumberFormatID475 selects Excelize number-format ID 475 with format code "[$FRF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID475 NumberFormat = 475
+ // NumberFormatID476 selects Excelize number-format ID 476 with format code "[$GBP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID476 NumberFormat = 476
+ // NumberFormatID477 selects Excelize number-format ID 477 with format code "[$GEL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID477 NumberFormat = 477
+ // NumberFormatID478 selects Excelize number-format ID 478 with format code "[$GHC]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID478 NumberFormat = 478
+ // NumberFormatID479 selects Excelize number-format ID 479 with format code "[$GHS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID479 NumberFormat = 479
+ // NumberFormatID480 selects Excelize number-format ID 480 with format code "[$GIP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID480 NumberFormat = 480
+ // NumberFormatID481 selects Excelize number-format ID 481 with format code "[$GMD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID481 NumberFormat = 481
+ // NumberFormatID482 selects Excelize number-format ID 482 with format code "[$GNF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID482 NumberFormat = 482
+ // NumberFormatID483 selects Excelize number-format ID 483 with format code "[$GRD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID483 NumberFormat = 483
+ // NumberFormatID484 selects Excelize number-format ID 484 with format code "[$GTQ]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID484 NumberFormat = 484
+ // NumberFormatID485 selects Excelize number-format ID 485 with format code "[$GYD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID485 NumberFormat = 485
+ // NumberFormatID486 selects Excelize number-format ID 486 with format code "[$HKD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID486 NumberFormat = 486
+ // NumberFormatID487 selects Excelize number-format ID 487 with format code "[$HNL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID487 NumberFormat = 487
+ // NumberFormatID488 selects Excelize number-format ID 488 with format code "[$HRK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID488 NumberFormat = 488
+ // NumberFormatID489 selects Excelize number-format ID 489 with format code "[$HTG]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID489 NumberFormat = 489
+ // NumberFormatID490 selects Excelize number-format ID 490 with format code "[$HUF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID490 NumberFormat = 490
+ // NumberFormatID491 selects Excelize number-format ID 491 with format code "[$IDR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID491 NumberFormat = 491
+ // NumberFormatID492 selects Excelize number-format ID 492 with format code "[$IEP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID492 NumberFormat = 492
+ // NumberFormatID493 selects Excelize number-format ID 493 with format code "[$ILS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID493 NumberFormat = 493
+ // NumberFormatID494 selects Excelize number-format ID 494 with format code "[$INR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID494 NumberFormat = 494
+ // NumberFormatID495 selects Excelize number-format ID 495 with format code "[$IQD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID495 NumberFormat = 495
+ // NumberFormatID496 selects Excelize number-format ID 496 with format code "[$IRR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID496 NumberFormat = 496
+ // NumberFormatID497 selects Excelize number-format ID 497 with format code "[$ISK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID497 NumberFormat = 497
+ // NumberFormatID498 selects Excelize number-format ID 498 with format code "[$ITL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID498 NumberFormat = 498
+ // NumberFormatID499 selects Excelize number-format ID 499 with format code "[$JMD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID499 NumberFormat = 499
+ // NumberFormatID500 selects Excelize number-format ID 500 with format code "[$JOD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID500 NumberFormat = 500
+ // NumberFormatID501 selects Excelize number-format ID 501 with format code "[$JPY]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID501 NumberFormat = 501
+ // NumberFormatID502 selects Excelize number-format ID 502 with format code "[$KAF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID502 NumberFormat = 502
+ // NumberFormatID503 selects Excelize number-format ID 503 with format code "[$KES]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID503 NumberFormat = 503
+ // NumberFormatID504 selects Excelize number-format ID 504 with format code "[$KGS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID504 NumberFormat = 504
+ // NumberFormatID505 selects Excelize number-format ID 505 with format code "[$KHR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID505 NumberFormat = 505
+ // NumberFormatID506 selects Excelize number-format ID 506 with format code "[$KMF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID506 NumberFormat = 506
+ // NumberFormatID507 selects Excelize number-format ID 507 with format code "[$KPW]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID507 NumberFormat = 507
+ // NumberFormatID508 selects Excelize number-format ID 508 with format code "[$KRW]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID508 NumberFormat = 508
+ // NumberFormatID509 selects Excelize number-format ID 509 with format code "[$KWD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID509 NumberFormat = 509
+ // NumberFormatID510 selects Excelize number-format ID 510 with format code "[$KYD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID510 NumberFormat = 510
+ // NumberFormatID511 selects Excelize number-format ID 511 with format code "[$KZT]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID511 NumberFormat = 511
+ // NumberFormatID512 selects Excelize number-format ID 512 with format code "[$LAK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID512 NumberFormat = 512
+ // NumberFormatID513 selects Excelize number-format ID 513 with format code "[$LBP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID513 NumberFormat = 513
+ // NumberFormatID514 selects Excelize number-format ID 514 with format code "[$LKR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID514 NumberFormat = 514
+ // NumberFormatID515 selects Excelize number-format ID 515 with format code "[$LRD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID515 NumberFormat = 515
+ // NumberFormatID516 selects Excelize number-format ID 516 with format code "[$LSL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID516 NumberFormat = 516
+ // NumberFormatID517 selects Excelize number-format ID 517 with format code "[$LTL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID517 NumberFormat = 517
+ // NumberFormatID518 selects Excelize number-format ID 518 with format code "[$LUF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID518 NumberFormat = 518
+ // NumberFormatID519 selects Excelize number-format ID 519 with format code "[$LVL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID519 NumberFormat = 519
+ // NumberFormatID520 selects Excelize number-format ID 520 with format code "[$LYD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID520 NumberFormat = 520
+ // NumberFormatID521 selects Excelize number-format ID 521 with format code "[$MAD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID521 NumberFormat = 521
+ // NumberFormatID522 selects Excelize number-format ID 522 with format code "[$MDL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID522 NumberFormat = 522
+ // NumberFormatID523 selects Excelize number-format ID 523 with format code "[$MGA]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID523 NumberFormat = 523
+ // NumberFormatID524 selects Excelize number-format ID 524 with format code "[$MGF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID524 NumberFormat = 524
+ // NumberFormatID525 selects Excelize number-format ID 525 with format code "[$MKD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID525 NumberFormat = 525
+ // NumberFormatID526 selects Excelize number-format ID 526 with format code "[$MMK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID526 NumberFormat = 526
+ // NumberFormatID527 selects Excelize number-format ID 527 with format code "[$MNT]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID527 NumberFormat = 527
+ // NumberFormatID528 selects Excelize number-format ID 528 with format code "[$MOP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID528 NumberFormat = 528
+ // NumberFormatID529 selects Excelize number-format ID 529 with format code "[$MRO]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID529 NumberFormat = 529
+ // NumberFormatID530 selects Excelize number-format ID 530 with format code "[$MTL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID530 NumberFormat = 530
+ // NumberFormatID531 selects Excelize number-format ID 531 with format code "[$MUR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID531 NumberFormat = 531
+ // NumberFormatID532 selects Excelize number-format ID 532 with format code "[$MVR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID532 NumberFormat = 532
+ // NumberFormatID533 selects Excelize number-format ID 533 with format code "[$MWK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID533 NumberFormat = 533
+ // NumberFormatID534 selects Excelize number-format ID 534 with format code "[$MXN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID534 NumberFormat = 534
+ // NumberFormatID535 selects Excelize number-format ID 535 with format code "[$MXV]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID535 NumberFormat = 535
+ // NumberFormatID536 selects Excelize number-format ID 536 with format code "[$MYR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID536 NumberFormat = 536
+ // NumberFormatID537 selects Excelize number-format ID 537 with format code "[$MZM]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID537 NumberFormat = 537
+ // NumberFormatID538 selects Excelize number-format ID 538 with format code "[$MZN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID538 NumberFormat = 538
+ // NumberFormatID539 selects Excelize number-format ID 539 with format code "[$NAD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID539 NumberFormat = 539
+ // NumberFormatID540 selects Excelize number-format ID 540 with format code "[$NGN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID540 NumberFormat = 540
+ // NumberFormatID541 selects Excelize number-format ID 541 with format code "[$NIO]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID541 NumberFormat = 541
+ // NumberFormatID542 selects Excelize number-format ID 542 with format code "[$NLG]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID542 NumberFormat = 542
+ // NumberFormatID543 selects Excelize number-format ID 543 with format code "[$NOK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID543 NumberFormat = 543
+ // NumberFormatID544 selects Excelize number-format ID 544 with format code "[$NPR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID544 NumberFormat = 544
+ // NumberFormatID545 selects Excelize number-format ID 545 with format code "[$NTD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID545 NumberFormat = 545
+ // NumberFormatID546 selects Excelize number-format ID 546 with format code "[$NZD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID546 NumberFormat = 546
+ // NumberFormatID547 selects Excelize number-format ID 547 with format code "[$OMR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID547 NumberFormat = 547
+ // NumberFormatID548 selects Excelize number-format ID 548 with format code "[$PAB]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID548 NumberFormat = 548
+ // NumberFormatID549 selects Excelize number-format ID 549 with format code "[$PEN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID549 NumberFormat = 549
+ // NumberFormatID550 selects Excelize number-format ID 550 with format code "[$PGK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID550 NumberFormat = 550
+ // NumberFormatID551 selects Excelize number-format ID 551 with format code "[$PHP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID551 NumberFormat = 551
+ // NumberFormatID552 selects Excelize number-format ID 552 with format code "[$PKR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID552 NumberFormat = 552
+ // NumberFormatID553 selects Excelize number-format ID 553 with format code "[$PLN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID553 NumberFormat = 553
+ // NumberFormatID554 selects Excelize number-format ID 554 with format code "[$PTE]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID554 NumberFormat = 554
+ // NumberFormatID555 selects Excelize number-format ID 555 with format code "[$PYG]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID555 NumberFormat = 555
+ // NumberFormatID556 selects Excelize number-format ID 556 with format code "[$QAR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID556 NumberFormat = 556
+ // NumberFormatID557 selects Excelize number-format ID 557 with format code "[$ROL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID557 NumberFormat = 557
+ // NumberFormatID558 selects Excelize number-format ID 558 with format code "[$RON]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID558 NumberFormat = 558
+ // NumberFormatID559 selects Excelize number-format ID 559 with format code "[$RSD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID559 NumberFormat = 559
+ // NumberFormatID560 selects Excelize number-format ID 560 with format code "[$RUB]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID560 NumberFormat = 560
+ // NumberFormatID561 selects Excelize number-format ID 561 with format code "[$RUR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID561 NumberFormat = 561
+ // NumberFormatID562 selects Excelize number-format ID 562 with format code "[$RWF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID562 NumberFormat = 562
+ // NumberFormatID563 selects Excelize number-format ID 563 with format code "[$SAR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID563 NumberFormat = 563
+ // NumberFormatID564 selects Excelize number-format ID 564 with format code "[$SBD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID564 NumberFormat = 564
+ // NumberFormatID565 selects Excelize number-format ID 565 with format code "[$SCR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID565 NumberFormat = 565
+ // NumberFormatID566 selects Excelize number-format ID 566 with format code "[$SDD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID566 NumberFormat = 566
+ // NumberFormatID567 selects Excelize number-format ID 567 with format code "[$SDG]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID567 NumberFormat = 567
+ // NumberFormatID568 selects Excelize number-format ID 568 with format code "[$SDP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID568 NumberFormat = 568
+ // NumberFormatID569 selects Excelize number-format ID 569 with format code "[$SEK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID569 NumberFormat = 569
+ // NumberFormatID570 selects Excelize number-format ID 570 with format code "[$SGD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID570 NumberFormat = 570
+ // NumberFormatID571 selects Excelize number-format ID 571 with format code "[$SHP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID571 NumberFormat = 571
+ // NumberFormatID572 selects Excelize number-format ID 572 with format code "[$SIT]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID572 NumberFormat = 572
+ // NumberFormatID573 selects Excelize number-format ID 573 with format code "[$SKK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID573 NumberFormat = 573
+ // NumberFormatID574 selects Excelize number-format ID 574 with format code "[$SLL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID574 NumberFormat = 574
+ // NumberFormatID575 selects Excelize number-format ID 575 with format code "[$SOS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID575 NumberFormat = 575
+ // NumberFormatID576 selects Excelize number-format ID 576 with format code "[$SPL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID576 NumberFormat = 576
+ // NumberFormatID577 selects Excelize number-format ID 577 with format code "[$SRD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID577 NumberFormat = 577
+ // NumberFormatID578 selects Excelize number-format ID 578 with format code "[$SRG]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID578 NumberFormat = 578
+ // NumberFormatID579 selects Excelize number-format ID 579 with format code "[$STD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID579 NumberFormat = 579
+ // NumberFormatID580 selects Excelize number-format ID 580 with format code "[$SVC]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID580 NumberFormat = 580
+ // NumberFormatID581 selects Excelize number-format ID 581 with format code "[$SYP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID581 NumberFormat = 581
+ // NumberFormatID582 selects Excelize number-format ID 582 with format code "[$SZL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID582 NumberFormat = 582
+ // NumberFormatID583 selects Excelize number-format ID 583 with format code "[$THB]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID583 NumberFormat = 583
+ // NumberFormatID584 selects Excelize number-format ID 584 with format code "[$TJR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID584 NumberFormat = 584
+ // NumberFormatID585 selects Excelize number-format ID 585 with format code "[$TJS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID585 NumberFormat = 585
+ // NumberFormatID586 selects Excelize number-format ID 586 with format code "[$TMM]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID586 NumberFormat = 586
+ // NumberFormatID587 selects Excelize number-format ID 587 with format code "[$TMT]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID587 NumberFormat = 587
+ // NumberFormatID588 selects Excelize number-format ID 588 with format code "[$TND]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID588 NumberFormat = 588
+ // NumberFormatID589 selects Excelize number-format ID 589 with format code "[$TOP]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID589 NumberFormat = 589
+ // NumberFormatID590 selects Excelize number-format ID 590 with format code "[$TRL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID590 NumberFormat = 590
+ // NumberFormatID591 selects Excelize number-format ID 591 with format code "[$TRY]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID591 NumberFormat = 591
+ // NumberFormatID592 selects Excelize number-format ID 592 with format code "[$TTD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID592 NumberFormat = 592
+ // NumberFormatID593 selects Excelize number-format ID 593 with format code "[$TWD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID593 NumberFormat = 593
+ // NumberFormatID594 selects Excelize number-format ID 594 with format code "[$TZS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID594 NumberFormat = 594
+ // NumberFormatID595 selects Excelize number-format ID 595 with format code "[$UAH]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID595 NumberFormat = 595
+ // NumberFormatID596 selects Excelize number-format ID 596 with format code "[$UGX]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID596 NumberFormat = 596
+ // NumberFormatID597 selects Excelize number-format ID 597 with format code "[$USD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID597 NumberFormat = 597
+ // NumberFormatID598 selects Excelize number-format ID 598 with format code "[$USN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID598 NumberFormat = 598
+ // NumberFormatID599 selects Excelize number-format ID 599 with format code "[$USS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID599 NumberFormat = 599
+ // NumberFormatID600 selects Excelize number-format ID 600 with format code "[$UYI]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID600 NumberFormat = 600
+ // NumberFormatID601 selects Excelize number-format ID 601 with format code "[$UYU]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID601 NumberFormat = 601
+ // NumberFormatID602 selects Excelize number-format ID 602 with format code "[$UZS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID602 NumberFormat = 602
+ // NumberFormatID603 selects Excelize number-format ID 603 with format code "[$VEB]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID603 NumberFormat = 603
+ // NumberFormatID604 selects Excelize number-format ID 604 with format code "[$VEF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID604 NumberFormat = 604
+ // NumberFormatID605 selects Excelize number-format ID 605 with format code "[$VND]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID605 NumberFormat = 605
+ // NumberFormatID606 selects Excelize number-format ID 606 with format code "[$VUV]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID606 NumberFormat = 606
+ // NumberFormatID607 selects Excelize number-format ID 607 with format code "[$WST]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID607 NumberFormat = 607
+ // NumberFormatID608 selects Excelize number-format ID 608 with format code "[$XAF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID608 NumberFormat = 608
+ // NumberFormatID609 selects Excelize number-format ID 609 with format code "[$XAG]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID609 NumberFormat = 609
+ // NumberFormatID610 selects Excelize number-format ID 610 with format code "[$XAU]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID610 NumberFormat = 610
+ // NumberFormatID611 selects Excelize number-format ID 611 with format code "[$XB5]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID611 NumberFormat = 611
+ // NumberFormatID612 selects Excelize number-format ID 612 with format code "[$XBA]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID612 NumberFormat = 612
+ // NumberFormatID613 selects Excelize number-format ID 613 with format code "[$XBB]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID613 NumberFormat = 613
+ // NumberFormatID614 selects Excelize number-format ID 614 with format code "[$XBC]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID614 NumberFormat = 614
+ // NumberFormatID615 selects Excelize number-format ID 615 with format code "[$XBD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID615 NumberFormat = 615
+ // NumberFormatID616 selects Excelize number-format ID 616 with format code "[$XCD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID616 NumberFormat = 616
+ // NumberFormatID617 selects Excelize number-format ID 617 with format code "[$XDR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID617 NumberFormat = 617
+ // NumberFormatID618 selects Excelize number-format ID 618 with format code "[$XFO]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID618 NumberFormat = 618
+ // NumberFormatID619 selects Excelize number-format ID 619 with format code "[$XFU]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID619 NumberFormat = 619
+ // NumberFormatID620 selects Excelize number-format ID 620 with format code "[$XOF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID620 NumberFormat = 620
+ // NumberFormatID621 selects Excelize number-format ID 621 with format code "[$XPD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID621 NumberFormat = 621
+ // NumberFormatID622 selects Excelize number-format ID 622 with format code "[$XPF]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID622 NumberFormat = 622
+ // NumberFormatID623 selects Excelize number-format ID 623 with format code "[$XPT]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID623 NumberFormat = 623
+ // NumberFormatID624 selects Excelize number-format ID 624 with format code "[$XTS]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID624 NumberFormat = 624
+ // NumberFormatID625 selects Excelize number-format ID 625 with format code "[$XXX]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID625 NumberFormat = 625
+ // NumberFormatID626 selects Excelize number-format ID 626 with format code "[$YER]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID626 NumberFormat = 626
+ // NumberFormatID627 selects Excelize number-format ID 627 with format code "[$YUM]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID627 NumberFormat = 627
+ // NumberFormatID628 selects Excelize number-format ID 628 with format code "[$ZAR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID628 NumberFormat = 628
+ // NumberFormatID629 selects Excelize number-format ID 629 with format code "[$ZMK]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID629 NumberFormat = 629
+ // NumberFormatID630 selects Excelize number-format ID 630 with format code "[$ZMW]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID630 NumberFormat = 630
+ // NumberFormatID631 selects Excelize number-format ID 631 with format code "[$ZWD]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID631 NumberFormat = 631
+ // NumberFormatID632 selects Excelize number-format ID 632 with format code "[$ZWL]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID632 NumberFormat = 632
+ // NumberFormatID633 selects Excelize number-format ID 633 with format code "[$ZWN]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID633 NumberFormat = 633
+ // NumberFormatID634 selects Excelize number-format ID 634 with format code "[$ZWR]\\ #,##0.00".
+ //
+ // See https://xuri.me/excelize/en/style.html
+ NumberFormatID634 NumberFormat = 634
+)
+
+func (value NumberFormat) Code() (string, bool) {
+ switch value {
+ case NumberFormatID0:
+ return "general", true
+ case NumberFormatID1:
+ return "0", true
+ case NumberFormatID2:
+ return "0.00", true
+ case NumberFormatID3:
+ return "#,##0", true
+ case NumberFormatID4:
+ return "#,##0.00", true
+ case NumberFormatID9:
+ return "0%", true
+ case NumberFormatID10:
+ return "0.00%", true
+ case NumberFormatID11:
+ return "0.00E+00", true
+ case NumberFormatID12:
+ return "# ?/?", true
+ case NumberFormatID13:
+ return "# ??/??", true
+ case NumberFormatID14:
+ return "mm-dd-yy", true
+ case NumberFormatID15:
+ return "d-mmm-yy", true
+ case NumberFormatID16:
+ return "d-mmm", true
+ case NumberFormatID17:
+ return "mmm-yy", true
+ case NumberFormatID18:
+ return "h:mm AM/PM", true
+ case NumberFormatID19:
+ return "h:mm:ss AM/PM", true
+ case NumberFormatID20:
+ return "hh:mm", true
+ case NumberFormatID21:
+ return "hh:mm:ss", true
+ case NumberFormatID22:
+ return "m/d/yy hh:mm", true
+ case NumberFormatID37:
+ return "#,##0 ;(#,##0)", true
+ case NumberFormatID38:
+ return "#,##0 ;[red](#,##0)", true
+ case NumberFormatID39:
+ return "#,##0.00 ;(#,##0.00)", true
+ case NumberFormatID40:
+ return "#,##0.00 ;[red](#,##0.00)", true
+ case NumberFormatID41:
+ return "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)", true
+ case NumberFormatID42:
+ return "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)", true
+ case NumberFormatID43:
+ return "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)", true
+ case NumberFormatID44:
+ return "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)", true
+ case NumberFormatID45:
+ return "mm:ss", true
+ case NumberFormatID46:
+ return "[h]:mm:ss", true
+ case NumberFormatID47:
+ return "mm:ss.0", true
+ case NumberFormatID48:
+ return "##0.0E+0", true
+ case NumberFormatID49:
+ return "@", true
+ case NumberFormatID164:
+ return "\"¥\"#,##0.00", true
+ case NumberFormatID165:
+ return "[$$-409]#,##0.00", true
+ case NumberFormatID166:
+ return "[$$-45C]#,##0.00", true
+ case NumberFormatID167:
+ return "[$$-1004]#,##0.00", true
+ case NumberFormatID168:
+ return "[$$-404]#,##0.00", true
+ case NumberFormatID169:
+ return "[$$-C09]#,##0.00", true
+ case NumberFormatID170:
+ return "[$$-2809]#,##0.00", true
+ case NumberFormatID171:
+ return "[$$-1009]#,##0.00", true
+ case NumberFormatID172:
+ return "[$$-2009]#,##0.00", true
+ case NumberFormatID173:
+ return "[$$-1409]#,##0.00", true
+ case NumberFormatID174:
+ return "[$$-4809]#,##0.00", true
+ case NumberFormatID175:
+ return "[$$-2C09]#,##0.00", true
+ case NumberFormatID176:
+ return "[$$-2409]#,##0.00", true
+ case NumberFormatID177:
+ return "[$$-1000]#,##0.00", true
+ case NumberFormatID178:
+ return "#,##0.00\\ [$$-C0C]", true
+ case NumberFormatID179:
+ return "[$$-475]#,##0.00", true
+ case NumberFormatID180:
+ return "[$$-83E]#,##0.00", true
+ case NumberFormatID181:
+ return "[$$-86B]\\ #,##0.00", true
+ case NumberFormatID182:
+ return "[$$-340A]\\ #,##0.00", true
+ case NumberFormatID183:
+ return "[$$-240A]#,##0.00", true
+ case NumberFormatID184:
+ return "[$$-300A]\\ #,##0.00", true
+ case NumberFormatID185:
+ return "[$$-440A]#,##0.00", true
+ case NumberFormatID186:
+ return "[$$-80A]#,##0.00", true
+ case NumberFormatID187:
+ return "[$$-500A]#,##0.00", true
+ case NumberFormatID188:
+ return "[$$-540A]#,##0.00", true
+ case NumberFormatID189:
+ return "[$$-380A]\\ #,##0.00", true
+ case NumberFormatID190:
+ return "[$£-809]#,##0.00", true
+ case NumberFormatID191:
+ return "[$£-491]#,##0.00", true
+ case NumberFormatID192:
+ return "[$£-452]#,##0.00", true
+ case NumberFormatID193:
+ return "[$¥-804]#,##0.00", true
+ case NumberFormatID194:
+ return "[$¥-411]#,##0.00", true
+ case NumberFormatID195:
+ return "[$¥-478]#,##0.00", true
+ case NumberFormatID196:
+ return "[$¥-451]#,##0.00", true
+ case NumberFormatID197:
+ return "[$¥-480]#,##0.00", true
+ case NumberFormatID198:
+ return "#,##0.00\\ [$֏-42B]", true
+ case NumberFormatID199:
+ return "[$؋-463]#,##0.00", true
+ case NumberFormatID200:
+ return "[$؋-48C]#,##0.00", true
+ case NumberFormatID201:
+ return "[$৳-845]\\ #,##0.00", true
+ case NumberFormatID202:
+ return "#,##0.00[$៛-453]", true
+ case NumberFormatID203:
+ return "[$₡-140A]#,##0.00", true
+ case NumberFormatID204:
+ return "[$₦-468]\\ #,##0.00", true
+ case NumberFormatID205:
+ return "[$₦-470]\\ #,##0.00", true
+ case NumberFormatID206:
+ return "[$₩-412]#,##0.00", true
+ case NumberFormatID207:
+ return "[$₪-40D]\\ #,##0.00", true
+ case NumberFormatID208:
+ return "#,##0.00\\ [$₫-42A]", true
+ case NumberFormatID209:
+ return "#,##0.00\\ [$€-42D]", true
+ case NumberFormatID210:
+ return "#,##0.00\\ [$€-47E]", true
+ case NumberFormatID211:
+ return "#,##0.00\\ [$€-403]", true
+ case NumberFormatID212:
+ return "#,##0.00\\ [$€-483]", true
+ case NumberFormatID213:
+ return "[$€-813]\\ #,##0.00", true
+ case NumberFormatID214:
+ return "[$€-413]\\ #,##0.00", true
+ case NumberFormatID215:
+ return "[$€-1809]#,##0.00", true
+ case NumberFormatID216:
+ return "#,##0.00\\ [$€-425]", true
+ case NumberFormatID217:
+ return "[$€-2]\\ #,##0.00", true
+ case NumberFormatID218:
+ return "#,##0.00\\ [$€-1]", true
+ case NumberFormatID219:
+ return "#,##0.00\\ [$€-40B]", true
+ case NumberFormatID220:
+ return "#,##0.00\\ [$€-80C]", true
+ case NumberFormatID221:
+ return "#,##0.00\\ [$€-40C]", true
+ case NumberFormatID222:
+ return "#,##0.00\\ [$€-140C]", true
+ case NumberFormatID223:
+ return "#,##0.00\\ [$€-180C]", true
+ case NumberFormatID224:
+ return "[$€-200C]#,##0.00", true
+ case NumberFormatID225:
+ return "#,##0.00\\ [$€-456]", true
+ case NumberFormatID226:
+ return "#,##0.00\\ [$€-C07]", true
+ case NumberFormatID227:
+ return "#,##0.00\\ [$€-407]", true
+ case NumberFormatID228:
+ return "#,##0.00\\ [$€-1007]", true
+ case NumberFormatID229:
+ return "#,##0.00\\ [$€-408]", true
+ case NumberFormatID230:
+ return "#,##0.00\\ [$€-243B]", true
+ case NumberFormatID231:
+ return "[$€-83C]#,##0.00", true
+ case NumberFormatID232:
+ return "[$€-410]\\ #,##0.00", true
+ case NumberFormatID233:
+ return "[$€-476]#,##0.00", true
+ case NumberFormatID234:
+ return "#,##0.00\\ [$€-2C1A]", true
+ case NumberFormatID235:
+ return "[$€-426]\\ #,##0.00", true
+ case NumberFormatID236:
+ return "#,##0.00\\ [$€-427]", true
+ case NumberFormatID237:
+ return "#,##0.00\\ [$€-82E]", true
+ case NumberFormatID238:
+ return "#,##0.00\\ [$€-46E]", true
+ case NumberFormatID239:
+ return "[$€-43A]#,##0.00", true
+ case NumberFormatID240:
+ return "#,##0.00\\ [$€-C3B]", true
+ case NumberFormatID241:
+ return "#,##0.00\\ [$€-482]", true
+ case NumberFormatID242:
+ return "#,##0.00\\ [$€-816]", true
+ case NumberFormatID243:
+ return "#,##0.00\\ [$€-301A]", true
+ case NumberFormatID244:
+ return "#,##0.00\\ [$€-203B]", true
+ case NumberFormatID245:
+ return "#,##0.00\\ [$€-41B]", true
+ case NumberFormatID246:
+ return "#,##0.00\\ [$€-424]", true
+ case NumberFormatID247:
+ return "#,##0.00\\ [$€-C0A]", true
+ case NumberFormatID248:
+ return "#,##0.00\\ [$€-81D]", true
+ case NumberFormatID249:
+ return "#,##0.00\\ [$€-484]", true
+ case NumberFormatID250:
+ return "#,##0.00\\ [$€-42E]", true
+ case NumberFormatID251:
+ return "[$€-462]\\ #,##0.00", true
+ case NumberFormatID252:
+ return "#,##0.00\\ [$₭-454]", true
+ case NumberFormatID253:
+ return "#,##0.00\\ [$₮-450]", true
+ case NumberFormatID254:
+ return "[$₮-C50]#,##0.00", true
+ case NumberFormatID255:
+ return "[$₱-3409]#,##0.00", true
+ case NumberFormatID256:
+ return "[$₱-464]#,##0.00", true
+ case NumberFormatID257:
+ return "#,##0.00[$₴-422]", true
+ case NumberFormatID258:
+ return "[$₸-43F]#,##0.00", true
+ case NumberFormatID259:
+ return "[$₹-460]#,##0.00", true
+ case NumberFormatID260:
+ return "[$₹-4009]\\ #,##0.00", true
+ case NumberFormatID261:
+ return "[$₹-447]\\ #,##0.00", true
+ case NumberFormatID262:
+ return "[$₹-439]\\ #,##0.00", true
+ case NumberFormatID263:
+ return "[$₹-44B]\\ #,##0.00", true
+ case NumberFormatID264:
+ return "[$₹-860]#,##0.00", true
+ case NumberFormatID265:
+ return "[$₹-457]\\ #,##0.00", true
+ case NumberFormatID266:
+ return "[$₹-458]#,##0.00", true
+ case NumberFormatID267:
+ return "[$₹-44E]\\ #,##0.00", true
+ case NumberFormatID268:
+ return "[$₹-861]#,##0.00", true
+ case NumberFormatID269:
+ return "[$₹-448]\\ #,##0.00", true
+ case NumberFormatID270:
+ return "[$₹-446]\\ #,##0.00", true
+ case NumberFormatID271:
+ return "[$₹-44F]\\ #,##0.00", true
+ case NumberFormatID272:
+ return "[$₹-459]#,##0.00", true
+ case NumberFormatID273:
+ return "[$₹-449]\\ #,##0.00", true
+ case NumberFormatID274:
+ return "[$₹-820]#,##0.00", true
+ case NumberFormatID275:
+ return "#,##0.00\\ [$₺-41F]", true
+ case NumberFormatID276:
+ return "#,##0.00\\ [$₼-42C]", true
+ case NumberFormatID277:
+ return "#,##0.00\\ [$₼-82C]", true
+ case NumberFormatID278:
+ return "#,##0.00\\ [$₽-419]", true
+ case NumberFormatID279:
+ return "#,##0.00[$₽-485]", true
+ case NumberFormatID280:
+ return "#,##0.00\\ [$₾-437]", true
+ case NumberFormatID281:
+ return "[$B/.-180A]\\ #,##0.00", true
+ case NumberFormatID282:
+ return "[$Br-472]#,##0.00", true
+ case NumberFormatID283:
+ return "[$Br-477]#,##0.00", true
+ case NumberFormatID284:
+ return "#,##0.00[$Br-473]", true
+ case NumberFormatID285:
+ return "[$Bs-46B]\\ #,##0.00", true
+ case NumberFormatID286:
+ return "[$Bs-400A]\\ #,##0.00", true
+ case NumberFormatID287:
+ return "[$Bs.-200A]\\ #,##0.00", true
+ case NumberFormatID288:
+ return "[$BWP-832]\\ #,##0.00", true
+ case NumberFormatID289:
+ return "[$C$-4C0A]#,##0.00", true
+ case NumberFormatID290:
+ return "[$CA$-85D]#,##0.00", true
+ case NumberFormatID291:
+ return "[$CA$-47C]#,##0.00", true
+ case NumberFormatID292:
+ return "[$CA$-45D]#,##0.00", true
+ case NumberFormatID293:
+ return "[$CFA-340C]#,##0.00", true
+ case NumberFormatID294:
+ return "[$CFA-280C]#,##0.00", true
+ case NumberFormatID295:
+ return "#,##0.00\\ [$CFA-867]", true
+ case NumberFormatID296:
+ return "#,##0.00\\ [$CFA-488]", true
+ case NumberFormatID297:
+ return "#,##0.00\\ [$CHF-100C]", true
+ case NumberFormatID298:
+ return "[$CHF-1407]\\ #,##0.00", true
+ case NumberFormatID299:
+ return "[$CHF-807]\\ #,##0.00", true
+ case NumberFormatID300:
+ return "[$CHF-810]\\ #,##0.00", true
+ case NumberFormatID301:
+ return "[$CHF-417]\\ #,##0.00", true
+ case NumberFormatID302:
+ return "[$CLP-47A]\\ #,##0.00", true
+ case NumberFormatID303:
+ return "[$CN¥-850]#,##0.00", true
+ case NumberFormatID304:
+ return "#,##0.00\\ [$DZD-85F]", true
+ case NumberFormatID305:
+ return "[$FCFA-2C0C]#,##0.00", true
+ case NumberFormatID306:
+ return "#,##0.00\\ [$Ft-40E]", true
+ case NumberFormatID307:
+ return "[$G-3C0C]#,##0.00", true
+ case NumberFormatID308:
+ return "[$Gs.-3C0A]\\ #,##0.00", true
+ case NumberFormatID309:
+ return "[$GTQ-486]#,##0.00", true
+ case NumberFormatID310:
+ return "[$HK$-C04]#,##0.00", true
+ case NumberFormatID311:
+ return "[$HK$-3C09]#,##0.00", true
+ case NumberFormatID312:
+ return "#,##0.00\\ [$HRK-41A]", true
+ case NumberFormatID313:
+ return "[$IDR-3809]#,##0.00", true
+ case NumberFormatID314:
+ return "[$IQD-492]#,##0.00", true
+ case NumberFormatID315:
+ return "#,##0.00\\ [$ISK-40F]", true
+ case NumberFormatID316:
+ return "[$K-455]#,##0.00", true
+ case NumberFormatID317:
+ return "#,##0.00\\ [$Kč-405]", true
+ case NumberFormatID318:
+ return "#,##0.00\\ [$KM-141A]", true
+ case NumberFormatID319:
+ return "#,##0.00\\ [$KM-101A]", true
+ case NumberFormatID320:
+ return "#,##0.00\\ [$KM-181A]", true
+ case NumberFormatID321:
+ return "[$kr-438]\\ #,##0.00", true
+ case NumberFormatID322:
+ return "[$kr-43B]\\ #,##0.00", true
+ case NumberFormatID323:
+ return "#,##0.00\\ [$kr-83B]", true
+ case NumberFormatID324:
+ return "[$kr-414]\\ #,##0.00", true
+ case NumberFormatID325:
+ return "[$kr-814]\\ #,##0.00", true
+ case NumberFormatID326:
+ return "#,##0.00\\ [$kr-41D]", true
+ case NumberFormatID327:
+ return "[$kr.-406]\\ #,##0.00", true
+ case NumberFormatID328:
+ return "[$kr.-46F]\\ #,##0.00", true
+ case NumberFormatID329:
+ return "[$Ksh-441]#,##0.00", true
+ case NumberFormatID330:
+ return "[$L-818]#,##0.00", true
+ case NumberFormatID331:
+ return "[$L-819]#,##0.00", true
+ case NumberFormatID332:
+ return "[$L-480A]\\ #,##0.00", true
+ case NumberFormatID333:
+ return "#,##0.00\\ [$Lekë-41C]", true
+ case NumberFormatID334:
+ return "[$MAD-45F]#,##0.00", true
+ case NumberFormatID335:
+ return "[$MAD-380C]#,##0.00", true
+ case NumberFormatID336:
+ return "#,##0.00\\ [$MAD-105F]", true
+ case NumberFormatID337:
+ return "[$MOP$-1404]#,##0.00", true
+ case NumberFormatID338:
+ return "#,##0.00\\ [$MVR-465]_-", true
+ case NumberFormatID339:
+ return "#,##0.00[$Nfk-873]", true
+ case NumberFormatID340:
+ return "[$NGN-466]#,##0.00", true
+ case NumberFormatID341:
+ return "[$NGN-467]#,##0.00", true
+ case NumberFormatID342:
+ return "[$NGN-469]#,##0.00", true
+ case NumberFormatID343:
+ return "[$NGN-471]#,##0.00", true
+ case NumberFormatID344:
+ return "[$NOK-103B]\\ #,##0.00", true
+ case NumberFormatID345:
+ return "[$NOK-183B]\\ #,##0.00", true
+ case NumberFormatID346:
+ return "[$NZ$-481]#,##0.00", true
+ case NumberFormatID347:
+ return "[$PKR-859]\\ #,##0.00", true
+ case NumberFormatID348:
+ return "[$PYG-474]#,##0.00", true
+ case NumberFormatID349:
+ return "[$Q-100A]#,##0.00", true
+ case NumberFormatID350:
+ return "[$R-436]\\ #,##0.00", true
+ case NumberFormatID351:
+ return "[$R-1C09]\\ #,##0.00", true
+ case NumberFormatID352:
+ return "[$R-435]\\ #,##0.00", true
+ case NumberFormatID353:
+ return "[$R$-416]\\ #,##0.00", true
+ case NumberFormatID354:
+ return "[$RD$-1C0A]#,##0.00", true
+ case NumberFormatID355:
+ return "#,##0.00\\ [$RF-487]", true
+ case NumberFormatID356:
+ return "[$RM-4409]#,##0.00", true
+ case NumberFormatID357:
+ return "[$RM-43E]#,##0.00", true
+ case NumberFormatID358:
+ return "#,##0.00\\ [$RON-418]", true
+ case NumberFormatID359:
+ return "[$Rp-421]#,##0.00", true
+ case NumberFormatID360:
+ return "[$Rs-420]#,##0.00_-", true
+ case NumberFormatID361:
+ return "[$Rs.-849]\\ #,##0.00", true
+ case NumberFormatID362:
+ return "#,##0.00\\ [$RSD-81A]", true
+ case NumberFormatID363:
+ return "#,##0.00\\ [$RSD-C1A]", true
+ case NumberFormatID364:
+ return "#,##0.00\\ [$RUB-46D]", true
+ case NumberFormatID365:
+ return "#,##0.00\\ [$RUB-444]", true
+ case NumberFormatID366:
+ return "[$S/.-C6B]\\ #,##0.00", true
+ case NumberFormatID367:
+ return "[$S/.-280A]\\ #,##0.00", true
+ case NumberFormatID368:
+ return "#,##0.00\\ [$SEK-143B]", true
+ case NumberFormatID369:
+ return "#,##0.00\\ [$SEK-1C3B]", true
+ case NumberFormatID370:
+ return "#,##0.00\\ [$soʻm-443]", true
+ case NumberFormatID371:
+ return "#,##0.00\\ [$soʻm-843]", true
+ case NumberFormatID372:
+ return "#,##0.00\\ [$SYP-45A]", true
+ case NumberFormatID373:
+ return "[$THB-41E]#,##0.00", true
+ case NumberFormatID374:
+ return "#,##0.00[$TMT-442]", true
+ case NumberFormatID375:
+ return "[$US$-3009]#,##0.00", true
+ case NumberFormatID376:
+ return "[$ZAR-46C]\\ #,##0.00", true
+ case NumberFormatID377:
+ return "[$ZAR-430]#,##0.00", true
+ case NumberFormatID378:
+ return "[$ZAR-431]#,##0.00", true
+ case NumberFormatID379:
+ return "[$ZAR-432]\\ #,##0.00", true
+ case NumberFormatID380:
+ return "[$ZAR-433]#,##0.00", true
+ case NumberFormatID381:
+ return "[$ZAR-434]\\ #,##0.00", true
+ case NumberFormatID382:
+ return "#,##0.00\\ [$zł-415]", true
+ case NumberFormatID383:
+ return "#,##0.00\\ [$ден-42F]", true
+ case NumberFormatID384:
+ return "#,##0.00\\ [$КМ-201A]", true
+ case NumberFormatID385:
+ return "#,##0.00\\ [$КМ-1C1A]", true
+ case NumberFormatID386:
+ return "#,##0.00\\ [$лв.-402]", true
+ case NumberFormatID387:
+ return "#,##0.00\\ [$р.-423]", true
+ case NumberFormatID388:
+ return "#,##0.00\\ [$сом-440]", true
+ case NumberFormatID389:
+ return "#,##0.00\\ [$сом-428]", true
+ case NumberFormatID390:
+ return "[$ج.م.-C01]\\ #,##0.00_-", true
+ case NumberFormatID391:
+ return "[$د.أ.-2C01]\\ #,##0.00_-", true
+ case NumberFormatID392:
+ return "[$د.إ.-3801]\\ #,##0.00_-", true
+ case NumberFormatID393:
+ return "[$د.ب.-3C01]\\ #,##0.00_-", true
+ case NumberFormatID394:
+ return "[$د.ت.-1C01]\\ #,##0.00_-", true
+ case NumberFormatID395:
+ return "[$د.ج.-1401]\\ #,##0.00_-", true
+ case NumberFormatID396:
+ return "[$د.ع.-801]\\ #,##0.00_-", true
+ case NumberFormatID397:
+ return "[$د.ك.-3401]\\ #,##0.00_-", true
+ case NumberFormatID398:
+ return "[$د.ل.-1001]#,##0.00_-", true
+ case NumberFormatID399:
+ return "[$د.م.-1801]\\ #,##0.00_-", true
+ case NumberFormatID400:
+ return "[$ر-846]\\ #,##0.00", true
+ case NumberFormatID401:
+ return "[$ر.س.-401]\\ #,##0.00_-", true
+ case NumberFormatID402:
+ return "[$ر.ع.-2001]\\ #,##0.00_-", true
+ case NumberFormatID403:
+ return "[$ر.ق.-4001]\\ #,##0.00_-", true
+ case NumberFormatID404:
+ return "[$ر.ي.-2401]\\ #,##0.00_-", true
+ case NumberFormatID405:
+ return "[$ریال-429]#,##0.00_-", true
+ case NumberFormatID406:
+ return "[$ل.س.-2801]\\ #,##0.00_-", true
+ case NumberFormatID407:
+ return "[$ل.ل.-3001]\\ #,##0.00_-", true
+ case NumberFormatID408:
+ return "[$ብር-45E]#,##0.00", true
+ case NumberFormatID409:
+ return "[$रू-461]#,##0.00", true
+ case NumberFormatID410:
+ return "[$රු.-45B]\\ #,##0.00", true
+ case NumberFormatID411:
+ return "[$ADP]\\ #,##0.00", true
+ case NumberFormatID412:
+ return "[$AED]\\ #,##0.00", true
+ case NumberFormatID413:
+ return "[$AFA]\\ #,##0.00", true
+ case NumberFormatID414:
+ return "[$AFN]\\ #,##0.00", true
+ case NumberFormatID415:
+ return "[$ALL]\\ #,##0.00", true
+ case NumberFormatID416:
+ return "[$AMD]\\ #,##0.00", true
+ case NumberFormatID417:
+ return "[$ANG]\\ #,##0.00", true
+ case NumberFormatID418:
+ return "[$AOA]\\ #,##0.00", true
+ case NumberFormatID419:
+ return "[$ARS]\\ #,##0.00", true
+ case NumberFormatID420:
+ return "[$ATS]\\ #,##0.00", true
+ case NumberFormatID421:
+ return "[$AUD]\\ #,##0.00", true
+ case NumberFormatID422:
+ return "[$AWG]\\ #,##0.00", true
+ case NumberFormatID423:
+ return "[$AZM]\\ #,##0.00", true
+ case NumberFormatID424:
+ return "[$AZN]\\ #,##0.00", true
+ case NumberFormatID425:
+ return "[$BAM]\\ #,##0.00", true
+ case NumberFormatID426:
+ return "[$BBD]\\ #,##0.00", true
+ case NumberFormatID427:
+ return "[$BDT]\\ #,##0.00", true
+ case NumberFormatID428:
+ return "[$BEF]\\ #,##0.00", true
+ case NumberFormatID429:
+ return "[$BGL]\\ #,##0.00", true
+ case NumberFormatID430:
+ return "[$BGN]\\ #,##0.00", true
+ case NumberFormatID431:
+ return "[$BHD]\\ #,##0.00", true
+ case NumberFormatID432:
+ return "[$BIF]\\ #,##0.00", true
+ case NumberFormatID433:
+ return "[$BMD]\\ #,##0.00", true
+ case NumberFormatID434:
+ return "[$BND]\\ #,##0.00", true
+ case NumberFormatID435:
+ return "[$BOB]\\ #,##0.00", true
+ case NumberFormatID436:
+ return "[$BOV]\\ #,##0.00", true
+ case NumberFormatID437:
+ return "[$BRL]\\ #,##0.00", true
+ case NumberFormatID438:
+ return "[$BSD]\\ #,##0.00", true
+ case NumberFormatID439:
+ return "[$BTN]\\ #,##0.00", true
+ case NumberFormatID440:
+ return "[$BWP]\\ #,##0.00", true
+ case NumberFormatID441:
+ return "[$BYR]\\ #,##0.00", true
+ case NumberFormatID442:
+ return "[$BZD]\\ #,##0.00", true
+ case NumberFormatID443:
+ return "[$CAD]\\ #,##0.00", true
+ case NumberFormatID444:
+ return "[$CDF]\\ #,##0.00", true
+ case NumberFormatID445:
+ return "[$CHE]\\ #,##0.00", true
+ case NumberFormatID446:
+ return "[$CHF]\\ #,##0.00", true
+ case NumberFormatID447:
+ return "[$CHW]\\ #,##0.00", true
+ case NumberFormatID448:
+ return "[$CLF]\\ #,##0.00", true
+ case NumberFormatID449:
+ return "[$CLP]\\ #,##0.00", true
+ case NumberFormatID450:
+ return "[$CNY]\\ #,##0.00", true
+ case NumberFormatID451:
+ return "[$COP]\\ #,##0.00", true
+ case NumberFormatID452:
+ return "[$COU]\\ #,##0.00", true
+ case NumberFormatID453:
+ return "[$CRC]\\ #,##0.00", true
+ case NumberFormatID454:
+ return "[$CSD]\\ #,##0.00", true
+ case NumberFormatID455:
+ return "[$CUC]\\ #,##0.00", true
+ case NumberFormatID456:
+ return "[$CVE]\\ #,##0.00", true
+ case NumberFormatID457:
+ return "[$CYP]\\ #,##0.00", true
+ case NumberFormatID458:
+ return "[$CZK]\\ #,##0.00", true
+ case NumberFormatID459:
+ return "[$DEM]\\ #,##0.00", true
+ case NumberFormatID460:
+ return "[$DJF]\\ #,##0.00", true
+ case NumberFormatID461:
+ return "[$DKK]\\ #,##0.00", true
+ case NumberFormatID462:
+ return "[$DOP]\\ #,##0.00", true
+ case NumberFormatID463:
+ return "[$DZD]\\ #,##0.00", true
+ case NumberFormatID464:
+ return "[$ECS]\\ #,##0.00", true
+ case NumberFormatID465:
+ return "[$ECV]\\ #,##0.00", true
+ case NumberFormatID466:
+ return "[$EEK]\\ #,##0.00", true
+ case NumberFormatID467:
+ return "[$EGP]\\ #,##0.00", true
+ case NumberFormatID468:
+ return "[$ERN]\\ #,##0.00", true
+ case NumberFormatID469:
+ return "[$ESP]\\ #,##0.00", true
+ case NumberFormatID470:
+ return "[$ETB]\\ #,##0.00", true
+ case NumberFormatID471:
+ return "[$EUR]\\ #,##0.00", true
+ case NumberFormatID472:
+ return "[$FIM]\\ #,##0.00", true
+ case NumberFormatID473:
+ return "[$FJD]\\ #,##0.00", true
+ case NumberFormatID474:
+ return "[$FKP]\\ #,##0.00", true
+ case NumberFormatID475:
+ return "[$FRF]\\ #,##0.00", true
+ case NumberFormatID476:
+ return "[$GBP]\\ #,##0.00", true
+ case NumberFormatID477:
+ return "[$GEL]\\ #,##0.00", true
+ case NumberFormatID478:
+ return "[$GHC]\\ #,##0.00", true
+ case NumberFormatID479:
+ return "[$GHS]\\ #,##0.00", true
+ case NumberFormatID480:
+ return "[$GIP]\\ #,##0.00", true
+ case NumberFormatID481:
+ return "[$GMD]\\ #,##0.00", true
+ case NumberFormatID482:
+ return "[$GNF]\\ #,##0.00", true
+ case NumberFormatID483:
+ return "[$GRD]\\ #,##0.00", true
+ case NumberFormatID484:
+ return "[$GTQ]\\ #,##0.00", true
+ case NumberFormatID485:
+ return "[$GYD]\\ #,##0.00", true
+ case NumberFormatID486:
+ return "[$HKD]\\ #,##0.00", true
+ case NumberFormatID487:
+ return "[$HNL]\\ #,##0.00", true
+ case NumberFormatID488:
+ return "[$HRK]\\ #,##0.00", true
+ case NumberFormatID489:
+ return "[$HTG]\\ #,##0.00", true
+ case NumberFormatID490:
+ return "[$HUF]\\ #,##0.00", true
+ case NumberFormatID491:
+ return "[$IDR]\\ #,##0.00", true
+ case NumberFormatID492:
+ return "[$IEP]\\ #,##0.00", true
+ case NumberFormatID493:
+ return "[$ILS]\\ #,##0.00", true
+ case NumberFormatID494:
+ return "[$INR]\\ #,##0.00", true
+ case NumberFormatID495:
+ return "[$IQD]\\ #,##0.00", true
+ case NumberFormatID496:
+ return "[$IRR]\\ #,##0.00", true
+ case NumberFormatID497:
+ return "[$ISK]\\ #,##0.00", true
+ case NumberFormatID498:
+ return "[$ITL]\\ #,##0.00", true
+ case NumberFormatID499:
+ return "[$JMD]\\ #,##0.00", true
+ case NumberFormatID500:
+ return "[$JOD]\\ #,##0.00", true
+ case NumberFormatID501:
+ return "[$JPY]\\ #,##0.00", true
+ case NumberFormatID502:
+ return "[$KAF]\\ #,##0.00", true
+ case NumberFormatID503:
+ return "[$KES]\\ #,##0.00", true
+ case NumberFormatID504:
+ return "[$KGS]\\ #,##0.00", true
+ case NumberFormatID505:
+ return "[$KHR]\\ #,##0.00", true
+ case NumberFormatID506:
+ return "[$KMF]\\ #,##0.00", true
+ case NumberFormatID507:
+ return "[$KPW]\\ #,##0.00", true
+ case NumberFormatID508:
+ return "[$KRW]\\ #,##0.00", true
+ case NumberFormatID509:
+ return "[$KWD]\\ #,##0.00", true
+ case NumberFormatID510:
+ return "[$KYD]\\ #,##0.00", true
+ case NumberFormatID511:
+ return "[$KZT]\\ #,##0.00", true
+ case NumberFormatID512:
+ return "[$LAK]\\ #,##0.00", true
+ case NumberFormatID513:
+ return "[$LBP]\\ #,##0.00", true
+ case NumberFormatID514:
+ return "[$LKR]\\ #,##0.00", true
+ case NumberFormatID515:
+ return "[$LRD]\\ #,##0.00", true
+ case NumberFormatID516:
+ return "[$LSL]\\ #,##0.00", true
+ case NumberFormatID517:
+ return "[$LTL]\\ #,##0.00", true
+ case NumberFormatID518:
+ return "[$LUF]\\ #,##0.00", true
+ case NumberFormatID519:
+ return "[$LVL]\\ #,##0.00", true
+ case NumberFormatID520:
+ return "[$LYD]\\ #,##0.00", true
+ case NumberFormatID521:
+ return "[$MAD]\\ #,##0.00", true
+ case NumberFormatID522:
+ return "[$MDL]\\ #,##0.00", true
+ case NumberFormatID523:
+ return "[$MGA]\\ #,##0.00", true
+ case NumberFormatID524:
+ return "[$MGF]\\ #,##0.00", true
+ case NumberFormatID525:
+ return "[$MKD]\\ #,##0.00", true
+ case NumberFormatID526:
+ return "[$MMK]\\ #,##0.00", true
+ case NumberFormatID527:
+ return "[$MNT]\\ #,##0.00", true
+ case NumberFormatID528:
+ return "[$MOP]\\ #,##0.00", true
+ case NumberFormatID529:
+ return "[$MRO]\\ #,##0.00", true
+ case NumberFormatID530:
+ return "[$MTL]\\ #,##0.00", true
+ case NumberFormatID531:
+ return "[$MUR]\\ #,##0.00", true
+ case NumberFormatID532:
+ return "[$MVR]\\ #,##0.00", true
+ case NumberFormatID533:
+ return "[$MWK]\\ #,##0.00", true
+ case NumberFormatID534:
+ return "[$MXN]\\ #,##0.00", true
+ case NumberFormatID535:
+ return "[$MXV]\\ #,##0.00", true
+ case NumberFormatID536:
+ return "[$MYR]\\ #,##0.00", true
+ case NumberFormatID537:
+ return "[$MZM]\\ #,##0.00", true
+ case NumberFormatID538:
+ return "[$MZN]\\ #,##0.00", true
+ case NumberFormatID539:
+ return "[$NAD]\\ #,##0.00", true
+ case NumberFormatID540:
+ return "[$NGN]\\ #,##0.00", true
+ case NumberFormatID541:
+ return "[$NIO]\\ #,##0.00", true
+ case NumberFormatID542:
+ return "[$NLG]\\ #,##0.00", true
+ case NumberFormatID543:
+ return "[$NOK]\\ #,##0.00", true
+ case NumberFormatID544:
+ return "[$NPR]\\ #,##0.00", true
+ case NumberFormatID545:
+ return "[$NTD]\\ #,##0.00", true
+ case NumberFormatID546:
+ return "[$NZD]\\ #,##0.00", true
+ case NumberFormatID547:
+ return "[$OMR]\\ #,##0.00", true
+ case NumberFormatID548:
+ return "[$PAB]\\ #,##0.00", true
+ case NumberFormatID549:
+ return "[$PEN]\\ #,##0.00", true
+ case NumberFormatID550:
+ return "[$PGK]\\ #,##0.00", true
+ case NumberFormatID551:
+ return "[$PHP]\\ #,##0.00", true
+ case NumberFormatID552:
+ return "[$PKR]\\ #,##0.00", true
+ case NumberFormatID553:
+ return "[$PLN]\\ #,##0.00", true
+ case NumberFormatID554:
+ return "[$PTE]\\ #,##0.00", true
+ case NumberFormatID555:
+ return "[$PYG]\\ #,##0.00", true
+ case NumberFormatID556:
+ return "[$QAR]\\ #,##0.00", true
+ case NumberFormatID557:
+ return "[$ROL]\\ #,##0.00", true
+ case NumberFormatID558:
+ return "[$RON]\\ #,##0.00", true
+ case NumberFormatID559:
+ return "[$RSD]\\ #,##0.00", true
+ case NumberFormatID560:
+ return "[$RUB]\\ #,##0.00", true
+ case NumberFormatID561:
+ return "[$RUR]\\ #,##0.00", true
+ case NumberFormatID562:
+ return "[$RWF]\\ #,##0.00", true
+ case NumberFormatID563:
+ return "[$SAR]\\ #,##0.00", true
+ case NumberFormatID564:
+ return "[$SBD]\\ #,##0.00", true
+ case NumberFormatID565:
+ return "[$SCR]\\ #,##0.00", true
+ case NumberFormatID566:
+ return "[$SDD]\\ #,##0.00", true
+ case NumberFormatID567:
+ return "[$SDG]\\ #,##0.00", true
+ case NumberFormatID568:
+ return "[$SDP]\\ #,##0.00", true
+ case NumberFormatID569:
+ return "[$SEK]\\ #,##0.00", true
+ case NumberFormatID570:
+ return "[$SGD]\\ #,##0.00", true
+ case NumberFormatID571:
+ return "[$SHP]\\ #,##0.00", true
+ case NumberFormatID572:
+ return "[$SIT]\\ #,##0.00", true
+ case NumberFormatID573:
+ return "[$SKK]\\ #,##0.00", true
+ case NumberFormatID574:
+ return "[$SLL]\\ #,##0.00", true
+ case NumberFormatID575:
+ return "[$SOS]\\ #,##0.00", true
+ case NumberFormatID576:
+ return "[$SPL]\\ #,##0.00", true
+ case NumberFormatID577:
+ return "[$SRD]\\ #,##0.00", true
+ case NumberFormatID578:
+ return "[$SRG]\\ #,##0.00", true
+ case NumberFormatID579:
+ return "[$STD]\\ #,##0.00", true
+ case NumberFormatID580:
+ return "[$SVC]\\ #,##0.00", true
+ case NumberFormatID581:
+ return "[$SYP]\\ #,##0.00", true
+ case NumberFormatID582:
+ return "[$SZL]\\ #,##0.00", true
+ case NumberFormatID583:
+ return "[$THB]\\ #,##0.00", true
+ case NumberFormatID584:
+ return "[$TJR]\\ #,##0.00", true
+ case NumberFormatID585:
+ return "[$TJS]\\ #,##0.00", true
+ case NumberFormatID586:
+ return "[$TMM]\\ #,##0.00", true
+ case NumberFormatID587:
+ return "[$TMT]\\ #,##0.00", true
+ case NumberFormatID588:
+ return "[$TND]\\ #,##0.00", true
+ case NumberFormatID589:
+ return "[$TOP]\\ #,##0.00", true
+ case NumberFormatID590:
+ return "[$TRL]\\ #,##0.00", true
+ case NumberFormatID591:
+ return "[$TRY]\\ #,##0.00", true
+ case NumberFormatID592:
+ return "[$TTD]\\ #,##0.00", true
+ case NumberFormatID593:
+ return "[$TWD]\\ #,##0.00", true
+ case NumberFormatID594:
+ return "[$TZS]\\ #,##0.00", true
+ case NumberFormatID595:
+ return "[$UAH]\\ #,##0.00", true
+ case NumberFormatID596:
+ return "[$UGX]\\ #,##0.00", true
+ case NumberFormatID597:
+ return "[$USD]\\ #,##0.00", true
+ case NumberFormatID598:
+ return "[$USN]\\ #,##0.00", true
+ case NumberFormatID599:
+ return "[$USS]\\ #,##0.00", true
+ case NumberFormatID600:
+ return "[$UYI]\\ #,##0.00", true
+ case NumberFormatID601:
+ return "[$UYU]\\ #,##0.00", true
+ case NumberFormatID602:
+ return "[$UZS]\\ #,##0.00", true
+ case NumberFormatID603:
+ return "[$VEB]\\ #,##0.00", true
+ case NumberFormatID604:
+ return "[$VEF]\\ #,##0.00", true
+ case NumberFormatID605:
+ return "[$VND]\\ #,##0.00", true
+ case NumberFormatID606:
+ return "[$VUV]\\ #,##0.00", true
+ case NumberFormatID607:
+ return "[$WST]\\ #,##0.00", true
+ case NumberFormatID608:
+ return "[$XAF]\\ #,##0.00", true
+ case NumberFormatID609:
+ return "[$XAG]\\ #,##0.00", true
+ case NumberFormatID610:
+ return "[$XAU]\\ #,##0.00", true
+ case NumberFormatID611:
+ return "[$XB5]\\ #,##0.00", true
+ case NumberFormatID612:
+ return "[$XBA]\\ #,##0.00", true
+ case NumberFormatID613:
+ return "[$XBB]\\ #,##0.00", true
+ case NumberFormatID614:
+ return "[$XBC]\\ #,##0.00", true
+ case NumberFormatID615:
+ return "[$XBD]\\ #,##0.00", true
+ case NumberFormatID616:
+ return "[$XCD]\\ #,##0.00", true
+ case NumberFormatID617:
+ return "[$XDR]\\ #,##0.00", true
+ case NumberFormatID618:
+ return "[$XFO]\\ #,##0.00", true
+ case NumberFormatID619:
+ return "[$XFU]\\ #,##0.00", true
+ case NumberFormatID620:
+ return "[$XOF]\\ #,##0.00", true
+ case NumberFormatID621:
+ return "[$XPD]\\ #,##0.00", true
+ case NumberFormatID622:
+ return "[$XPF]\\ #,##0.00", true
+ case NumberFormatID623:
+ return "[$XPT]\\ #,##0.00", true
+ case NumberFormatID624:
+ return "[$XTS]\\ #,##0.00", true
+ case NumberFormatID625:
+ return "[$XXX]\\ #,##0.00", true
+ case NumberFormatID626:
+ return "[$YER]\\ #,##0.00", true
+ case NumberFormatID627:
+ return "[$YUM]\\ #,##0.00", true
+ case NumberFormatID628:
+ return "[$ZAR]\\ #,##0.00", true
+ case NumberFormatID629:
+ return "[$ZMK]\\ #,##0.00", true
+ case NumberFormatID630:
+ return "[$ZMW]\\ #,##0.00", true
+ case NumberFormatID631:
+ return "[$ZWD]\\ #,##0.00", true
+ case NumberFormatID632:
+ return "[$ZWL]\\ #,##0.00", true
+ case NumberFormatID633:
+ return "[$ZWN]\\ #,##0.00", true
+ case NumberFormatID634:
+ return "[$ZWR]\\ #,##0.00", true
+ default:
+ return "", false
+ }
+}
+
+// StyleLanguage identifies a language tag in Excelize's localized number-format tables; newer Style APIs use the resolved format code.
+//
+// See https://xuri.me/excelize/en/style.html
+type StyleLanguage string
+
+const (
+ // StyleLanguageJa_jp identifies language tag "ja-jp" for localized number-format lookup.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleLanguageJa_jp StyleLanguage = "ja-jp"
+ // StyleLanguageKo_kr identifies language tag "ko-kr" for localized number-format lookup.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleLanguageKo_kr StyleLanguage = "ko-kr"
+ // StyleLanguageTh_th identifies language tag "th-th" for localized number-format lookup.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleLanguageTh_th StyleLanguage = "th-th"
+ // StyleLanguageZh_cn identifies language tag "zh-cn" for localized number-format lookup.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleLanguageZh_cn StyleLanguage = "zh-cn"
+ // StyleLanguageZh_tw identifies language tag "zh-tw" for localized number-format lookup.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleLanguageZh_tw StyleLanguage = "zh-tw"
+)
+
+func StyleLanguageValues() []StyleLanguage {
+ return []StyleLanguage{"ja-jp", "ko-kr", "th-th", "zh-cn", "zh-tw"}
+}
+
+func (value NumberFormat) CodeForLanguage(language StyleLanguage) (string, bool) {
+ switch language {
+ case "ja-jp":
+ switch value {
+ case NumberFormatID27:
+ return "[$-411]ge.m.d", true
+ case NumberFormatID28:
+ return "[$-411]ggge\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID29:
+ return "[$-411]ggge\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID30:
+ return "m/d/yy", true
+ case NumberFormatID31:
+ return "yyyy\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID32:
+ return "h\"時\"mm\"分\"", true
+ case NumberFormatID33:
+ return "h\"時\"mm\"分\"ss\"秒\"", true
+ case NumberFormatID34:
+ return "yyyy\"年\"m\"月\"", true
+ case NumberFormatID35:
+ return "m\"月\"d\"日\"", true
+ case NumberFormatID36:
+ return "[$-411]ge.m.d", true
+ case NumberFormatID50:
+ return "[$-411]ge.m.d", true
+ case NumberFormatID51:
+ return "[$-411]ggge\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID52:
+ return "yyyy\"年\"m\"月\"", true
+ case NumberFormatID53:
+ return "m\"月\"d\"日\"", true
+ case NumberFormatID54:
+ return "[$-411]ggge\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID55:
+ return "yyyy\"年\"m\"月\"", true
+ case NumberFormatID56:
+ return "m\"月\"d\"日\"", true
+ case NumberFormatID57:
+ return "[$-411]ge.m.d", true
+ case NumberFormatID58:
+ return "[$-411]ggge\"年\"m\"月\"d\"日\"", true
+ }
+ case "ko-kr":
+ switch value {
+ case NumberFormatID27:
+ return "yyyy\"年\" mm\"月\" dd\"日\"", true
+ case NumberFormatID28:
+ return "mm-dd", true
+ case NumberFormatID29:
+ return "mm-dd", true
+ case NumberFormatID30:
+ return "mm-dd-yy", true
+ case NumberFormatID31:
+ return "yyyy\"년\" mm\"월\" dd\"일\"", true
+ case NumberFormatID32:
+ return "h\"시\" mm\"분\"", true
+ case NumberFormatID33:
+ return "h\"시\" mm\"분\" ss\"초\"", true
+ case NumberFormatID34:
+ return "yyyy-mm-dd", true
+ case NumberFormatID35:
+ return "yyyy-mm-dd", true
+ case NumberFormatID36:
+ return "yyyy\"年\" mm\"月\" dd\"日\"", true
+ case NumberFormatID50:
+ return "yyyy\"年\" mm\"月\" dd\"日\"", true
+ case NumberFormatID51:
+ return "mm-dd", true
+ case NumberFormatID52:
+ return "yyyy-mm-dd", true
+ case NumberFormatID53:
+ return "yyyy-mm-dd", true
+ case NumberFormatID54:
+ return "mm-dd", true
+ case NumberFormatID55:
+ return "yyyy-mm-dd", true
+ case NumberFormatID56:
+ return "yyyy-mm-dd", true
+ case NumberFormatID57:
+ return "yyyy\"年\" mm\"月\" dd\"日\"", true
+ case NumberFormatID58:
+ return "mm-dd", true
+ }
+ case "th-th":
+ switch value {
+ case NumberFormatID59:
+ return "t0", true
+ case NumberFormatID60:
+ return "t0.00", true
+ case NumberFormatID61:
+ return "t#,##0", true
+ case NumberFormatID62:
+ return "t#,##0.00", true
+ case NumberFormatID67:
+ return "t0%", true
+ case NumberFormatID68:
+ return "t0.00%", true
+ case NumberFormatID69:
+ return "t# ?/?", true
+ case NumberFormatID70:
+ return "t# ??/??", true
+ case NumberFormatID71:
+ return "ว/ด/ปปปป", true
+ case NumberFormatID72:
+ return "ว-ดดด-ปป", true
+ case NumberFormatID73:
+ return "ว-ดดด", true
+ case NumberFormatID74:
+ return "ดดด-ปป", true
+ case NumberFormatID75:
+ return "ช:นน", true
+ case NumberFormatID76:
+ return "ช:นน:ทท", true
+ case NumberFormatID77:
+ return "ว/ด/ปปปป ช:นน", true
+ case NumberFormatID78:
+ return "นน:ทท", true
+ case NumberFormatID79:
+ return "[ช]:นน:ทท", true
+ case NumberFormatID80:
+ return "นน:ทท.0", true
+ case NumberFormatID81:
+ return "d/m/bb", true
+ }
+ case "zh-cn":
+ switch value {
+ case NumberFormatID27:
+ return "yyyy\"年\"m\"月\"", true
+ case NumberFormatID28:
+ return "m\"月\"d\"日\"", true
+ case NumberFormatID29:
+ return "m\"月\"d\"日\"", true
+ case NumberFormatID30:
+ return "m/d/yy", true
+ case NumberFormatID31:
+ return "yyyy\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID32:
+ return "h\"时\"mm\"分\"", true
+ case NumberFormatID33:
+ return "h\"时\"mm\"分\"ss\"秒\"", true
+ case NumberFormatID34:
+ return "上午/下午h\"时\"mm\"分\"", true
+ case NumberFormatID35:
+ return "上午/下午h\"时\"mm\"分\"ss\"秒\"", true
+ case NumberFormatID36:
+ return "yyyy\"年\"m\"月\"", true
+ case NumberFormatID50:
+ return "yyyy\"年\"m\"月\"", true
+ case NumberFormatID51:
+ return "m\"月\"d\"日\"", true
+ case NumberFormatID52:
+ return "yyyy\"年\"m\"月\"", true
+ case NumberFormatID53:
+ return "m\"月\"d\"日\"", true
+ case NumberFormatID54:
+ return "m\"月\"d\"日\"", true
+ case NumberFormatID55:
+ return "上午/下午h\"时\"mm\"分\"", true
+ case NumberFormatID56:
+ return "上午/下午h\"时\"mm\"分\"ss\"秒\"", true
+ case NumberFormatID57:
+ return "yyyy\"年\"m\"月\"", true
+ case NumberFormatID58:
+ return "m\"月\"d\"日\"", true
+ }
+ case "zh-tw":
+ switch value {
+ case NumberFormatID27:
+ return "[$-404]e/m/d", true
+ case NumberFormatID28:
+ return "[$-404]e\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID29:
+ return "[$-404]e\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID30:
+ return "m/d/yy", true
+ case NumberFormatID31:
+ return "yyyy\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID32:
+ return "hh\"時\"mm\"分\"", true
+ case NumberFormatID33:
+ return "hh\"時\"mm\"分\"ss\"秒\"", true
+ case NumberFormatID34:
+ return "上午/下午hh\"時\"mm\"分\"", true
+ case NumberFormatID35:
+ return "上午/下午hh\"時\"mm\"分\"ss\"秒\"", true
+ case NumberFormatID36:
+ return "[$-404]e/m/d", true
+ case NumberFormatID50:
+ return "[$-404]e/m/d", true
+ case NumberFormatID51:
+ return "[$-404]e\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID52:
+ return "上午/下午hh\"時\"mm\"分\"", true
+ case NumberFormatID53:
+ return "上午/下午hh\"時\"mm\"分\"ss\"秒\"", true
+ case NumberFormatID54:
+ return "[$-404]e\"年\"m\"月\"d\"日\"", true
+ case NumberFormatID55:
+ return "上午/下午hh\"時\"mm\"分\"", true
+ case NumberFormatID56:
+ return "上午/下午hh\"時\"mm\"分\"ss\"秒\"", true
+ case NumberFormatID57:
+ return "[$-404]e/m/d", true
+ case NumberFormatID58:
+ return "[$-404]e\"年\"m\"月\"d\"日\"", true
+ }
+ }
+ return value.Code()
+}
+
+// AlignmentField identifies a public field of excelize.Alignment; these values are field names rather than formatting values.
+//
+// See https://xuri.me/excelize/en/style.html
+type AlignmentField string
+
+const (
+ // AlignmentFieldHorizontal identifies excelize.Alignment.Horizontal.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentFieldHorizontal AlignmentField = "Horizontal"
+ // AlignmentFieldIndent identifies excelize.Alignment.Indent.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentFieldIndent AlignmentField = "Indent"
+ // AlignmentFieldJustifyLastLine identifies excelize.Alignment.JustifyLastLine.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentFieldJustifyLastLine AlignmentField = "JustifyLastLine"
+ // AlignmentFieldReadingOrder identifies excelize.Alignment.ReadingOrder.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentFieldReadingOrder AlignmentField = "ReadingOrder"
+ // AlignmentFieldRelativeIndent identifies excelize.Alignment.RelativeIndent.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentFieldRelativeIndent AlignmentField = "RelativeIndent"
+ // AlignmentFieldShrinkToFit identifies excelize.Alignment.ShrinkToFit.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentFieldShrinkToFit AlignmentField = "ShrinkToFit"
+ // AlignmentFieldTextRotation identifies excelize.Alignment.TextRotation.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentFieldTextRotation AlignmentField = "TextRotation"
+ // AlignmentFieldVertical identifies excelize.Alignment.Vertical.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentFieldVertical AlignmentField = "Vertical"
+ // AlignmentFieldWrapText identifies excelize.Alignment.WrapText.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ AlignmentFieldWrapText AlignmentField = "WrapText"
+)
+
+func AlignmentFieldValues() []AlignmentField {
+ return []AlignmentField{"Horizontal", "Indent", "JustifyLastLine", "ReadingOrder", "RelativeIndent", "ShrinkToFit", "TextRotation", "Vertical", "WrapText"}
+}
+
+// BorderField identifies a public field of excelize.Border; these values are field names rather than formatting values.
+//
+// See https://xuri.me/excelize/en/style.html
+type BorderField string
+
+const (
+ // BorderFieldType identifies excelize.Border.Type.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderFieldType BorderField = "Type"
+ // BorderFieldColor identifies excelize.Border.Color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderFieldColor BorderField = "Color"
+ // BorderFieldStyle identifies excelize.Border.Style.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ BorderFieldStyle BorderField = "Style"
+)
+
+func BorderFieldValues() []BorderField { return []BorderField{"Type", "Color", "Style"} }
+
+// FontField identifies a public field of excelize.Font; these values are field names rather than formatting values.
+//
+// See https://xuri.me/excelize/en/style.html
+type FontField string
+
+const (
+ // FontFieldBold identifies excelize.Font.Bold.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldBold FontField = "Bold"
+ // FontFieldItalic identifies excelize.Font.Italic.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldItalic FontField = "Italic"
+ // FontFieldUnderline identifies excelize.Font.Underline.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldUnderline FontField = "Underline"
+ // FontFieldFamily identifies excelize.Font.Family.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldFamily FontField = "Family"
+ // FontFieldSize identifies excelize.Font.Size.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldSize FontField = "Size"
+ // FontFieldStrike identifies excelize.Font.Strike.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldStrike FontField = "Strike"
+ // FontFieldColor identifies excelize.Font.Color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldColor FontField = "Color"
+ // FontFieldColorIndexed identifies excelize.Font.ColorIndexed.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldColorIndexed FontField = "ColorIndexed"
+ // FontFieldColorTheme identifies excelize.Font.ColorTheme.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldColorTheme FontField = "ColorTheme"
+ // FontFieldColorTint identifies excelize.Font.ColorTint.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldColorTint FontField = "ColorTint"
+ // FontFieldVertAlign identifies excelize.Font.VertAlign.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldVertAlign FontField = "VertAlign"
+ // FontFieldCharset identifies excelize.Font.Charset.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontFieldCharset FontField = "Charset"
+)
+
+func FontFieldValues() []FontField {
+ return []FontField{"Bold", "Italic", "Underline", "Family", "Size", "Strike", "Color", "ColorIndexed", "ColorTheme", "ColorTint", "VertAlign", "Charset"}
+}
+
+// FillField identifies a public field of excelize.Fill; these values are field names rather than formatting values.
+//
+// See https://xuri.me/excelize/en/style.html
+type FillField string
+
+const (
+ // FillFieldType identifies excelize.Fill.Type.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillFieldType FillField = "Type"
+ // FillFieldPattern identifies excelize.Fill.Pattern.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillFieldPattern FillField = "Pattern"
+ // FillFieldColor identifies excelize.Fill.Color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillFieldColor FillField = "Color"
+ // FillFieldShading identifies excelize.Fill.Shading.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillFieldShading FillField = "Shading"
+ // FillFieldTransparency identifies excelize.Fill.Transparency.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FillFieldTransparency FillField = "Transparency"
+)
+
+func FillFieldValues() []FillField {
+ return []FillField{"Type", "Pattern", "Color", "Shading", "Transparency"}
+}
+
+// ProtectionField identifies a public field of excelize.Protection; these values are field names rather than formatting values.
+//
+// See https://xuri.me/excelize/en/style.html
+type ProtectionField string
+
+const (
+ // ProtectionFieldHidden identifies excelize.Protection.Hidden.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ProtectionFieldHidden ProtectionField = "Hidden"
+ // ProtectionFieldLocked identifies excelize.Protection.Locked.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ProtectionFieldLocked ProtectionField = "Locked"
+)
+
+func ProtectionFieldValues() []ProtectionField { return []ProtectionField{"Hidden", "Locked"} }
+
+// StyleField identifies a public field of excelize.Style; these values are field names rather than formatting values.
+//
+// See https://xuri.me/excelize/en/style.html
+type StyleField string
+
+const (
+ // StyleFieldBorder identifies excelize.Style.Border.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleFieldBorder StyleField = "Border"
+ // StyleFieldFill identifies excelize.Style.Fill.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleFieldFill StyleField = "Fill"
+ // StyleFieldFont identifies excelize.Style.Font.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleFieldFont StyleField = "Font"
+ // StyleFieldAlignment identifies excelize.Style.Alignment.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleFieldAlignment StyleField = "Alignment"
+ // StyleFieldProtection identifies excelize.Style.Protection.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleFieldProtection StyleField = "Protection"
+ // StyleFieldNumFmt identifies excelize.Style.NumFmt.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleFieldNumFmt StyleField = "NumFmt"
+ // StyleFieldDecimalPlaces identifies excelize.Style.DecimalPlaces.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleFieldDecimalPlaces StyleField = "DecimalPlaces"
+ // StyleFieldCustomNumFmt identifies excelize.Style.CustomNumFmt.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleFieldCustomNumFmt StyleField = "CustomNumFmt"
+ // StyleFieldNegRed identifies excelize.Style.NegRed.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ StyleFieldNegRed StyleField = "NegRed"
+)
+
+func StyleFieldValues() []StyleField {
+ return []StyleField{"Border", "Fill", "Font", "Alignment", "Protection", "NumFmt", "DecimalPlaces", "CustomNumFmt", "NegRed"}
+}
+
+// IndexedColor selects an indexed palette entry or system color for excelize.Font.ColorIndexed; workbook palettes can override the displayed RGB.
+//
+// See https://xuri.me/excelize/en/style.html
+type IndexedColor int
+
+const (
+ // IndexedColorUnset leaves the indexed font color selector unspecified (ID -1).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorUnset IndexedColor = -1
+ // IndexedColorIndex0 selects palette index 0; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex0 IndexedColor = 0
+ // IndexedColorIndex1 selects palette index 1; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex1 IndexedColor = 1
+ // IndexedColorIndex2 selects palette index 2; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex2 IndexedColor = 2
+ // IndexedColorIndex3 selects palette index 3; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex3 IndexedColor = 3
+ // IndexedColorIndex4 selects palette index 4; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex4 IndexedColor = 4
+ // IndexedColorIndex5 selects palette index 5; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex5 IndexedColor = 5
+ // IndexedColorIndex6 selects palette index 6; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex6 IndexedColor = 6
+ // IndexedColorIndex7 selects palette index 7; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex7 IndexedColor = 7
+ // IndexedColorIndex8 selects palette index 8; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex8 IndexedColor = 8
+ // IndexedColorIndex9 selects palette index 9; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex9 IndexedColor = 9
+ // IndexedColorIndex10 selects palette index 10; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex10 IndexedColor = 10
+ // IndexedColorIndex11 selects palette index 11; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex11 IndexedColor = 11
+ // IndexedColorIndex12 selects palette index 12; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex12 IndexedColor = 12
+ // IndexedColorIndex13 selects palette index 13; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex13 IndexedColor = 13
+ // IndexedColorIndex14 selects palette index 14; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex14 IndexedColor = 14
+ // IndexedColorIndex15 selects palette index 15; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex15 IndexedColor = 15
+ // IndexedColorIndex16 selects palette index 16; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex16 IndexedColor = 16
+ // IndexedColorIndex17 selects palette index 17; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex17 IndexedColor = 17
+ // IndexedColorIndex18 selects palette index 18; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex18 IndexedColor = 18
+ // IndexedColorIndex19 selects palette index 19; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex19 IndexedColor = 19
+ // IndexedColorIndex20 selects palette index 20; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex20 IndexedColor = 20
+ // IndexedColorIndex21 selects palette index 21; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex21 IndexedColor = 21
+ // IndexedColorIndex22 selects palette index 22; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex22 IndexedColor = 22
+ // IndexedColorIndex23 selects palette index 23; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex23 IndexedColor = 23
+ // IndexedColorIndex24 selects palette index 24; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex24 IndexedColor = 24
+ // IndexedColorIndex25 selects palette index 25; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex25 IndexedColor = 25
+ // IndexedColorIndex26 selects palette index 26; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex26 IndexedColor = 26
+ // IndexedColorIndex27 selects palette index 27; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex27 IndexedColor = 27
+ // IndexedColorIndex28 selects palette index 28; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex28 IndexedColor = 28
+ // IndexedColorIndex29 selects palette index 29; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex29 IndexedColor = 29
+ // IndexedColorIndex30 selects palette index 30; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex30 IndexedColor = 30
+ // IndexedColorIndex31 selects palette index 31; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex31 IndexedColor = 31
+ // IndexedColorIndex32 selects palette index 32; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex32 IndexedColor = 32
+ // IndexedColorIndex33 selects palette index 33; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex33 IndexedColor = 33
+ // IndexedColorIndex34 selects palette index 34; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex34 IndexedColor = 34
+ // IndexedColorIndex35 selects palette index 35; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex35 IndexedColor = 35
+ // IndexedColorIndex36 selects palette index 36; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex36 IndexedColor = 36
+ // IndexedColorIndex37 selects palette index 37; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex37 IndexedColor = 37
+ // IndexedColorIndex38 selects palette index 38; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex38 IndexedColor = 38
+ // IndexedColorIndex39 selects palette index 39; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex39 IndexedColor = 39
+ // IndexedColorIndex40 selects palette index 40; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex40 IndexedColor = 40
+ // IndexedColorIndex41 selects palette index 41; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex41 IndexedColor = 41
+ // IndexedColorIndex42 selects palette index 42; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex42 IndexedColor = 42
+ // IndexedColorIndex43 selects palette index 43; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex43 IndexedColor = 43
+ // IndexedColorIndex44 selects palette index 44; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex44 IndexedColor = 44
+ // IndexedColorIndex45 selects palette index 45; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex45 IndexedColor = 45
+ // IndexedColorIndex46 selects palette index 46; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex46 IndexedColor = 46
+ // IndexedColorIndex47 selects palette index 47; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex47 IndexedColor = 47
+ // IndexedColorIndex48 selects palette index 48; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex48 IndexedColor = 48
+ // IndexedColorIndex49 selects palette index 49; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex49 IndexedColor = 49
+ // IndexedColorIndex50 selects palette index 50; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex50 IndexedColor = 50
+ // IndexedColorIndex51 selects palette index 51; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex51 IndexedColor = 51
+ // IndexedColorIndex52 selects palette index 52; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex52 IndexedColor = 52
+ // IndexedColorIndex53 selects palette index 53; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex53 IndexedColor = 53
+ // IndexedColorIndex54 selects palette index 54; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex54 IndexedColor = 54
+ // IndexedColorIndex55 selects palette index 55; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex55 IndexedColor = 55
+ // IndexedColorIndex56 selects palette index 56; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex56 IndexedColor = 56
+ // IndexedColorIndex57 selects palette index 57; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex57 IndexedColor = 57
+ // IndexedColorIndex58 selects palette index 58; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex58 IndexedColor = 58
+ // IndexedColorIndex59 selects palette index 59; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex59 IndexedColor = 59
+ // IndexedColorIndex60 selects palette index 60; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex60 IndexedColor = 60
+ // IndexedColorIndex61 selects palette index 61; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex61 IndexedColor = 61
+ // IndexedColorIndex62 selects palette index 62; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex62 IndexedColor = 62
+ // IndexedColorIndex63 selects palette index 63; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex63 IndexedColor = 63
+ // IndexedColorIndex64 selects palette index 64; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex64 IndexedColor = 64
+ // IndexedColorIndex65 selects palette index 65; the workbook palette determines its RGB color.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorIndex65 IndexedColor = 65
+ // IndexedColorSystemForeground selects the system foreground color (index 64).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorSystemForeground IndexedColor = 64
+ // IndexedColorSystemBackground selects the system background color (index 65).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ IndexedColorSystemBackground IndexedColor = 65
+)
+
+// ThemeColor selects a workbook theme slot for excelize.Font.ColorTheme; its displayed color depends on the workbook theme.
+//
+// See https://xuri.me/excelize/en/style.html
+type ThemeColor int
+
+const (
+ // ThemeColorLight1 selects the workbook theme's Light1 color slot (ID 0).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorLight1 ThemeColor = 0
+ // ThemeColorDark1 selects the workbook theme's Dark1 color slot (ID 1).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorDark1 ThemeColor = 1
+ // ThemeColorLight2 selects the workbook theme's Light2 color slot (ID 2).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorLight2 ThemeColor = 2
+ // ThemeColorDark2 selects the workbook theme's Dark2 color slot (ID 3).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorDark2 ThemeColor = 3
+ // ThemeColorAccent1 selects the workbook theme's Accent1 color slot (ID 4).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorAccent1 ThemeColor = 4
+ // ThemeColorAccent2 selects the workbook theme's Accent2 color slot (ID 5).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorAccent2 ThemeColor = 5
+ // ThemeColorAccent3 selects the workbook theme's Accent3 color slot (ID 6).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorAccent3 ThemeColor = 6
+ // ThemeColorAccent4 selects the workbook theme's Accent4 color slot (ID 7).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorAccent4 ThemeColor = 7
+ // ThemeColorAccent5 selects the workbook theme's Accent5 color slot (ID 8).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorAccent5 ThemeColor = 8
+ // ThemeColorAccent6 selects the workbook theme's Accent6 color slot (ID 9).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorAccent6 ThemeColor = 9
+ // ThemeColorHyperlink selects the workbook theme's Hyperlink color slot (ID 10).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorHyperlink ThemeColor = 10
+ // ThemeColorFollowedHyperlink selects the workbook theme's FollowedHyperlink color slot (ID 11).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ ThemeColorFollowedHyperlink ThemeColor = 11
+)
+
+// FontCharset identifies an OOXML font character set for excelize.Font.Charset; these numeric selectors are not RGB colors or text encodings to apply to cell values.
+//
+// See https://xuri.me/excelize/en/style.html
+type FontCharset int
+
+const (
+ // FontCharsetANSI selects the ANSI font character set (ID 0).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetANSI FontCharset = 0
+ // FontCharsetDefault selects the Default font character set (ID 1).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetDefault FontCharset = 1
+ // FontCharsetSymbol selects the Symbol font character set (ID 2).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetSymbol FontCharset = 2
+ // FontCharsetMac selects the Mac font character set (ID 77).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetMac FontCharset = 77
+ // FontCharsetShiftJIS selects the ShiftJIS font character set (ID 128).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetShiftJIS FontCharset = 128
+ // FontCharsetHangul selects the Hangul font character set (ID 129).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetHangul FontCharset = 129
+ // FontCharsetJohab selects the Johab font character set (ID 130).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetJohab FontCharset = 130
+ // FontCharsetGB2312 selects the GB2312 font character set (ID 134).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetGB2312 FontCharset = 134
+ // FontCharsetBig5 selects the Big5 font character set (ID 136).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetBig5 FontCharset = 136
+ // FontCharsetGreek selects the Greek font character set (ID 161).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetGreek FontCharset = 161
+ // FontCharsetTurkish selects the Turkish font character set (ID 162).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetTurkish FontCharset = 162
+ // FontCharsetVietnamese selects the Vietnamese font character set (ID 163).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetVietnamese FontCharset = 163
+ // FontCharsetHebrew selects the Hebrew font character set (ID 177).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetHebrew FontCharset = 177
+ // FontCharsetArabic selects the Arabic font character set (ID 178).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetArabic FontCharset = 178
+ // FontCharsetBaltic selects the Baltic font character set (ID 186).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetBaltic FontCharset = 186
+ // FontCharsetRussian selects the Russian font character set (ID 204).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetRussian FontCharset = 204
+ // FontCharsetThai selects the Thai font character set (ID 222).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetThai FontCharset = 222
+ // FontCharsetEastEurope selects the EastEurope font character set (ID 238).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetEastEurope FontCharset = 238
+ // FontCharsetOEM selects the OEM font character set (ID 255).
+ //
+ // See https://xuri.me/excelize/en/style.html
+ FontCharsetOEM FontCharset = 255
+)
+
+// AlignmentDefinition preserves all public excelize.Alignment fields with typed categorical values.
+type AlignmentDefinition struct {
+ Horizontal AlignmentHorizontal
+ Indent int
+ JustifyLastLine bool
+ ReadingOrder AlignmentReadingOrder
+ RelativeIndent int
+ ShrinkToFit bool
+ TextRotation int
+ Vertical AlignmentVertical
+ WrapText bool
+}
+
+func (in AlignmentDefinition) ToExcelize() excelize.Alignment {
+ out := excelize.Alignment{}
+ out.Horizontal = string(in.Horizontal)
+ out.Indent = in.Indent
+ out.JustifyLastLine = in.JustifyLastLine
+ out.ReadingOrder = uint64(in.ReadingOrder)
+ out.RelativeIndent = in.RelativeIndent
+ out.ShrinkToFit = in.ShrinkToFit
+ out.TextRotation = in.TextRotation
+ out.Vertical = string(in.Vertical)
+ out.WrapText = in.WrapText
+ return out
+}
+func AlignmentDefinitionFromExcelize(in excelize.Alignment) AlignmentDefinition {
+ out := AlignmentDefinition{}
+ out.Horizontal = AlignmentHorizontal(in.Horizontal)
+ out.Indent = in.Indent
+ out.JustifyLastLine = in.JustifyLastLine
+ out.ReadingOrder = AlignmentReadingOrder(in.ReadingOrder)
+ out.RelativeIndent = in.RelativeIndent
+ out.ShrinkToFit = in.ShrinkToFit
+ out.TextRotation = in.TextRotation
+ out.Vertical = AlignmentVertical(in.Vertical)
+ out.WrapText = in.WrapText
+ return out
+}
+
+// BorderDefinition preserves all public excelize.Border fields with typed categorical values.
+type BorderDefinition struct {
+ Type BorderPosition
+ Color string
+ Style BorderStyle
+}
+
+func (in BorderDefinition) ToExcelize() excelize.Border {
+ out := excelize.Border{}
+ out.Type = string(in.Type)
+ out.Color = in.Color
+ out.Style = int(in.Style)
+ return out
+}
+func BorderDefinitionFromExcelize(in excelize.Border) BorderDefinition {
+ out := BorderDefinition{}
+ out.Type = BorderPosition(in.Type)
+ out.Color = in.Color
+ out.Style = BorderStyle(in.Style)
+ return out
+}
+
+// FontDefinition preserves all public excelize.Font fields with typed categorical values.
+type FontDefinition struct {
+ Bold bool
+ Italic bool
+ Underline FontUnderline
+ Family string
+ Size float64
+ Strike bool
+ Color string
+ ColorIndexed IndexedColor
+ ColorTheme *ThemeColor
+ ColorTint float64
+ VertAlign FontVerticalAlign
+ Charset *FontCharset
+}
+
+func (in FontDefinition) ToExcelize() excelize.Font {
+ out := excelize.Font{}
+ out.Bold = in.Bold
+ out.Italic = in.Italic
+ out.Underline = string(in.Underline)
+ out.Family = in.Family
+ out.Size = in.Size
+ out.Strike = in.Strike
+ out.Color = in.Color
+ out.ColorIndexed = int(in.ColorIndexed)
+ if in.ColorTheme != nil {
+ value := int(*in.ColorTheme)
+ out.ColorTheme = &value
+ }
+ out.ColorTint = in.ColorTint
+ out.VertAlign = string(in.VertAlign)
+ if in.Charset != nil {
+ value := int(*in.Charset)
+ out.Charset = &value
+ }
+ return out
+}
+func FontDefinitionFromExcelize(in excelize.Font) FontDefinition {
+ out := FontDefinition{}
+ out.Bold = in.Bold
+ out.Italic = in.Italic
+ out.Underline = FontUnderline(in.Underline)
+ out.Family = in.Family
+ out.Size = in.Size
+ out.Strike = in.Strike
+ out.Color = in.Color
+ out.ColorIndexed = IndexedColor(in.ColorIndexed)
+ if in.ColorTheme != nil {
+ value := ThemeColor(*in.ColorTheme)
+ out.ColorTheme = &value
+ }
+ out.ColorTint = in.ColorTint
+ out.VertAlign = FontVerticalAlign(in.VertAlign)
+ if in.Charset != nil {
+ value := FontCharset(*in.Charset)
+ out.Charset = &value
+ }
+ return out
+}
+
+// FillDefinition preserves all public excelize.Fill fields with typed categorical values.
+type FillDefinition struct {
+ Type FillType
+ Pattern FillPattern
+ Color []string
+ Shading GradientShading
+ Transparency int
+}
+
+func (in FillDefinition) ToExcelize() excelize.Fill {
+ out := excelize.Fill{}
+ out.Type = string(in.Type)
+ out.Pattern = int(in.Pattern)
+ out.Color = in.Color
+ out.Shading = int(in.Shading)
+ out.Transparency = in.Transparency
+ return out
+}
+func FillDefinitionFromExcelize(in excelize.Fill) FillDefinition {
+ out := FillDefinition{}
+ out.Type = FillType(in.Type)
+ out.Pattern = FillPattern(in.Pattern)
+ out.Color = in.Color
+ out.Shading = GradientShading(in.Shading)
+ out.Transparency = in.Transparency
+ return out
+}
+
+// ProtectionDefinition preserves all public excelize.Protection fields with typed categorical values.
+type ProtectionDefinition struct {
+ Hidden bool
+ Locked bool
+}
+
+func (in ProtectionDefinition) ToExcelize() excelize.Protection {
+ out := excelize.Protection{}
+ out.Hidden = in.Hidden
+ out.Locked = in.Locked
+ return out
+}
+func ProtectionDefinitionFromExcelize(in excelize.Protection) ProtectionDefinition {
+ out := ProtectionDefinition{}
+ out.Hidden = in.Hidden
+ out.Locked = in.Locked
+ return out
+}
+
+// StyleDefinition preserves all public excelize.Style fields with typed categorical values.
+type StyleDefinition struct {
+ Border []BorderDefinition
+ Fill FillDefinition
+ Font *FontDefinition
+ Alignment *AlignmentDefinition
+ Protection *ProtectionDefinition
+ NumFmt NumberFormat
+ DecimalPlaces *int
+ CustomNumFmt *string
+ NegRed bool
+}
+
+func (in StyleDefinition) ToExcelize() excelize.Style {
+ out := excelize.Style{}
+ if in.Border != nil {
+ out.Border = make([]excelize.Border, len(in.Border))
+ for i, value := range in.Border {
+ out.Border[i] = value.ToExcelize()
+ }
+ }
+ out.Fill = in.Fill.ToExcelize()
+ if in.Font != nil {
+ value := in.Font.ToExcelize()
+ out.Font = &value
+ }
+ if in.Alignment != nil {
+ value := in.Alignment.ToExcelize()
+ out.Alignment = &value
+ }
+ if in.Protection != nil {
+ value := in.Protection.ToExcelize()
+ out.Protection = &value
+ }
+ out.NumFmt = int(in.NumFmt)
+ out.DecimalPlaces = in.DecimalPlaces
+ out.CustomNumFmt = in.CustomNumFmt
+ out.NegRed = in.NegRed
+ return out
+}
+func StyleDefinitionFromExcelize(in excelize.Style) StyleDefinition {
+ out := StyleDefinition{}
+ if in.Border != nil {
+ out.Border = make([]BorderDefinition, len(in.Border))
+ for i, value := range in.Border {
+ out.Border[i] = BorderDefinitionFromExcelize(value)
+ }
+ }
+ out.Fill = FillDefinitionFromExcelize(in.Fill)
+ if in.Font != nil {
+ value := FontDefinitionFromExcelize(*in.Font)
+ out.Font = &value
+ }
+ if in.Alignment != nil {
+ value := AlignmentDefinitionFromExcelize(*in.Alignment)
+ out.Alignment = &value
+ }
+ if in.Protection != nil {
+ value := ProtectionDefinitionFromExcelize(*in.Protection)
+ out.Protection = &value
+ }
+ out.NumFmt = NumberFormat(in.NumFmt)
+ out.DecimalPlaces = in.DecimalPlaces
+ out.CustomNumFmt = in.CustomNumFmt
+ out.NegRed = in.NegRed
+ return out
+}
+
+// GradientShading selects a gradient preset in the selected Excelize dependency; preset numbering may change between versions.
+//
+// See https://xuri.me/excelize/en/style.html
+type GradientShading int
+
+const (
+ // GradientShadingPreset0 selects preset 0: linear gradient, degree 90, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset0 GradientShading = 0
+ // GradientShadingPreset1 selects preset 1: linear gradient, degree 270, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset1 GradientShading = 1
+ // GradientShadingPreset2 selects preset 2: linear gradient, degree 90, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,0.5,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset2 GradientShading = 2
+ // GradientShadingPreset3 selects preset 3: linear gradient, degree 0, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset3 GradientShading = 3
+ // GradientShadingPreset4 selects preset 4: linear gradient, degree 180, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset4 GradientShading = 4
+ // GradientShadingPreset5 selects preset 5: linear gradient, degree 0, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,0.5,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset5 GradientShading = 5
+ // GradientShadingPreset6 selects preset 6: linear gradient, degree 45, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset6 GradientShading = 6
+ // GradientShadingPreset7 selects preset 7: linear gradient, degree 255, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset7 GradientShading = 7
+ // GradientShadingPreset8 selects preset 8: linear gradient, degree 45, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,0.5,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset8 GradientShading = 8
+ // GradientShadingPreset9 selects preset 9: linear gradient, degree 135, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset9 GradientShading = 9
+ // GradientShadingPreset10 selects preset 10: linear gradient, degree 315, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset10 GradientShading = 10
+ // GradientShadingPreset11 selects preset 11: linear gradient, degree 135, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,0.5,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset11 GradientShading = 11
+ // GradientShadingPreset12 selects preset 12: path gradient, degree 0, path bounds (left 0, right 0, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset12 GradientShading = 12
+ // GradientShadingPreset13 selects preset 13: path gradient, degree 0, path bounds (left 1, right 1, top 0, bottom 0), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset13 GradientShading = 13
+ // GradientShadingPreset14 selects preset 14: path gradient, degree 0, path bounds (left 0, right 0, top 1, bottom 1), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset14 GradientShading = 14
+ // GradientShadingPreset15 selects preset 15: path gradient, degree 0, path bounds (left 1, right 1, top 1, bottom 1), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset15 GradientShading = 15
+ // GradientShadingPreset16 selects preset 16: path gradient, degree 0, path bounds (left 0.5, right 0.5, top 0.5, bottom 0.5), and stop positions [0,1].
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingPreset16 GradientShading = 16
+ // GradientShadingCount is the number of generated choices; it is not a valid formatting value.
+ //
+ // See https://xuri.me/excelize/en/style.html
+ GradientShadingCount GradientShading = 17
+)
diff --git a/excelizestyle/style_test.go b/excelizestyle/style_test.go
new file mode 100644
index 0000000..231ff7e
--- /dev/null
+++ b/excelizestyle/style_test.go
@@ -0,0 +1,109 @@
+package excelizestyle
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/xuri/excelize/v2"
+)
+
+func TestStyleDefinitionPreservesEveryField(t *testing.T) {
+ var original excelize.Style
+ populate(reflect.ValueOf(&original).Elem())
+ converted := StyleDefinitionFromExcelize(original).ToExcelize()
+ if !reflect.DeepEqual(original, converted) {
+ t.Fatalf("typed conversion lost a field:\noriginal: %#v\nconverted: %#v", original, converted)
+ }
+ // Nil and empty slices are observably different and must survive conversion.
+ empty := excelize.Style{Border: []excelize.Border{}}
+ if got := StyleDefinitionFromExcelize(empty).ToExcelize(); !reflect.DeepEqual(empty, got) {
+ t.Fatal("empty Border changed to nil")
+ }
+ if got := StyleDefinitionFromExcelize(excelize.Style{}).ToExcelize(); !reflect.DeepEqual(excelize.Style{}, got) {
+ t.Fatal("zero Style changed")
+ }
+}
+
+func populate(v reflect.Value) {
+ switch v.Kind() {
+ case reflect.Struct:
+ for i := 0; i < v.NumField(); i++ {
+ if v.Field(i).CanSet() {
+ populate(v.Field(i))
+ }
+ }
+ case reflect.Ptr:
+ v.Set(reflect.New(v.Type().Elem()))
+ populate(v.Elem())
+ case reflect.Slice:
+ v.Set(reflect.MakeSlice(v.Type(), 2, 2))
+ for i := 0; i < v.Len(); i++ {
+ populate(v.Index(i))
+ }
+ case reflect.Bool:
+ v.SetBool(true)
+ case reflect.Int, reflect.Int64:
+ v.SetInt(7)
+ case reflect.Uint64:
+ v.SetUint(2)
+ case reflect.Float64:
+ v.SetFloat(0.25)
+ case reflect.String:
+ v.SetString("custom-value")
+ }
+}
+
+func TestGeneratedFieldsMatchExcelize(t *testing.T) {
+ inventories := []struct {
+ value interface{}
+ fields []string
+ }{
+ {excelize.Style{}, stringsOf(StyleFieldValues())},
+ {excelize.Border{}, stringsOf(BorderFieldValues())},
+ {excelize.Fill{}, stringsOf(FillFieldValues())},
+ {excelize.Font{}, stringsOf(FontFieldValues())},
+ {excelize.Alignment{}, stringsOf(AlignmentFieldValues())},
+ {excelize.Protection{}, stringsOf(ProtectionFieldValues())},
+ }
+ for _, inventory := range inventories {
+ typ := reflect.TypeOf(inventory.value)
+ var expected []string
+ for i := 0; i < typ.NumField(); i++ {
+ if typ.Field(i).PkgPath == "" {
+ expected = append(expected, typ.Field(i).Name)
+ }
+ }
+ if !reflect.DeepEqual(expected, inventory.fields) {
+ t.Errorf("%s generated fields are stale; run go generate ./excelizeutil: want %v, got %v", typ.Name(), expected, inventory.fields)
+ }
+ }
+}
+
+func stringsOf[T ~string](values []T) []string {
+ result := make([]string, len(values))
+ for i, v := range values {
+ result[i] = string(v)
+ }
+ return result
+}
+
+func TestGeneratedEnumsAndExistingAliases(t *testing.T) {
+ if BorderStyleContinuous0 != BorderStyleHair || BorderStyleDash2 != BorderStyleMediumDashed || BorderStyleSlantDash != BorderStyleSlantDashDot {
+ t.Fatal("existing border aliases changed")
+ }
+ if AlignmentVerticalBottom != "bottom" || BorderPositionDiagonalUp != "diagonalUp" || BorderPositionDiagonalDown != "diagonalDown" {
+ t.Fatal("missing categorical values")
+ }
+ if code, ok := NumberFormatID14.Code(); !ok || code == "" {
+ t.Fatal("missing builtin number format")
+ }
+ if _, ok := NumberFormat(999999).Code(); ok {
+ t.Fatal("unknown number format accepted")
+ }
+ for _, pattern := range []FillPattern{FillPatternNone, FillPatternSolid, FillPatternGray0625} {
+ got, ok := ParseFillPattern(pattern.String())
+ if !ok || got != pattern {
+ t.Fatal("fill enum conversion changed")
+ }
+ }
+}
diff --git a/excelizeutil/STYLE_COVERAGE.md b/excelizeutil/STYLE_COVERAGE.md
new file mode 100644
index 0000000..d571837
--- /dev/null
+++ b/excelizeutil/STYLE_COVERAGE.md
@@ -0,0 +1,53 @@
+# `excelize.Style` の取得・再適用範囲
+
+## 対象バージョンと契約
+
+この表は、PR の統合ツリーで使われる Excelize **v2.10.1** の `excelize.Style` を基準にしています。対応する公開型の全40フィールドを棚卸しし、セルの実効書式を取得して `NewStyle` で再適用できる範囲を定義します。元の `NewStyle` 入力を復元することや、任意の OOXML を無損失で複製することは契約に含めません。
+
+PR ブランチは main の依存更新を取り込み、Excelize v2.10.1 を使用します。生成器は v2.6.0 の旧定義形式にも対応しますが、依存バージョンを変更した場合は `go generate ./excelizeutil` で型付き定義を再生成する必要があります。v2.6.0 には `Style.Lang` があり、`DecimalPlaces` は `int`、`Fill.Transparency` と Font の色参照フィールドはありません。v2.10.1 には `Style.Lang` がなく、`DecimalPlaces` は `*int` です。旧版の `Lang` 入力は workbook から一意に復元できず、選択された完全な書式コードを保持します。gradient は依存中の AST から生成し、v2.10.1 の17 preset と v2.6.0 の6 preset をそれぞれ扱います。
+
+フィールド定義の根拠は Excelize の固定タグにある [`xmlStyles.go`](https://github.com/qax-os/excelize/blob/v2.10.1/xmlStyles.go)、[`styles.go`](https://github.com/qax-os/excelize/blob/v2.10.1/styles.go)、[`numfmt.go`](https://github.com/qax-os/excelize/blob/v2.10.1/numfmt.go) です。
+
+## フィールド対応表
+
+| 型 | 公開フィールド | 取得・再適用と検証 |
+|---|---|---|
+| `Style` | `Border`, `Fill`, `Font`, `Alignment`, `Protection` | 下記の各型に従って実効値を取得し、保存・再読込後に同じ書式となることを確認します。 |
+| `Style` | `NumFmt`, `CustomNumFmt` | 組み込み ID は `NumFmt`、ユーザー定義コードは完全な書式文字列を `CustomNumFmt` に保持します。組み込み形式と quoted/escaped 文字を含む独自形式を再適用テストします。 |
+| `Style` | `DecimalPlaces`, `NegRed` | v2.10.1 の組み込み形式では Excelize の `GetStyle` が返す値を使います。独自形式では decimal 数や `[Red]` を文字列から推測せず、同じ意味を持つ完全な `CustomNumFmt` を保存します。組み込みの decimal 数は個別に再適用テストします。 |
+| `Border` | `Type`, `Color`, `Style` | 6種類の辺と style 0〜13を検証します。色は実効 RGB で保持します。 |
+| `Fill` | `Type`, `Pattern`, `Color` | pattern 0〜18と単色を検証します。`Color` は foreground を優先し、なければ background を取得します。 |
+| `Fill` | `Shading` | v2.10.1 の全17 gradient preset を、geometry、stop 数、stop 位置、終端色まで確認します。v2.6.0 では同バージョンの6 preset を使います。 |
+| `Fill` | `Transparency` | v2.10.1 の公開フィールドですが、Excelize では chart / shape 用でセル書式には保存されません。セル書式の取得・再適用対象外です。 |
+| `Font` | `Bold`, `Italic`, `Strike` | boolean 属性を保持します。値のない ``、``、`` は OOXML の既定に従って `true` とします。各項目の保存後 XML と値を検証します。 |
+| `Font` | `Underline`, `Family`, `Size`, `VertAlign`, `Charset` | 取得後に再適用し、XML 属性と再読込値を確認します。v2.10.1 固有の `VertAlign` / `Charset` は v2.6.0 では型にありません。 |
+| `Font` | `Color` | v2.10.1 では OOXML に RGB がある場合に限り、Tint 適用前の RGB を保持します。theme / indexed のみの色では空です。これにより同じ tint を二度適用しません。v2.6.0 は色参照フィールドがないため、解決した見た目の RGB を返します。RGB のみで再適用する見た目も別に検証します。 |
+| `Font` | `ColorIndexed`, `ColorTheme`, `ColorTint` | v2.10.1 では元の selector と tint を保持し、同じ theme / palette の workbook で再適用できることを確認します。色の selector と見た目の RGB は別々に検証します。v2.6.0 ではこれらの公開フィールドがありません。 |
+| `Alignment` | `Horizontal`, `Vertical`, `Indent`, `RelativeIndent`, `ReadingOrder`, `TextRotation`, `WrapText`, `ShrinkToFit`, `JustifyLastLine` | 9項目を全て設定し、返却値、保存・再読込後の値、再出力 XML の全属性を検証します。親 `cellStyleXfs` からの継承も確認します。 |
+| `Protection` | `Hidden`, `Locked` | 両方の値を保持します。XMLで `locked` が省略された場合は既定値 `true` として扱います。属性省略、明示的な解除 (`locked="0"`)、親 `cellStyleXfs` からの継承を、保存・再読込と XML 属性で検証します。 |
+
+`applyFont="0"` の `cellXfs` は参照先 `cellStyleXfs` のフォントを継承する規則です。親の `fontId="0"` も有効な参照として扱い、親フォント0をカスタマイズした fixture の取得・別 workbook への再適用・再読込を確認します。`applyFont="1"` で `fontId` が省略された場合も、実装が解決する font ID 0 を適用し、カスタム font0 の再適用を確認します。`applyFont` / `applyAlignment` / `applyProtection` の継承規則は [MS-OE376 §3.8.45](https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/59922f8b-0edc-4e93-a822-9f22254aec46) に記載されています。CT_Xf で `fontId` は optional 属性、ID は `` collection への0-based indexです([ECMA-376 §3.8.45](https://c-rex.net/samples/ooxml/e1/Part4/OOXML_P4_DOCX_xf_topic_ID0E13S6.html))。
+
+## 再適用できない入力
+
+- v2.10.1 の gradient は17 preset に対応します。3 stop の preset 2・5・8・11 は、position が `0, 0.5, 1` で、最初と最後の実効色が同じ場合に限り、`Style.Fill.Color` の2色へ縮約できます。gradient の任意 geometry、任意 stop 配置、異なる3つ目の色は公開 `Style` で表現できません。未対応 gradient は種類だけを返し、色を返さないため、そのまま `NewStyle` へ渡すとエラーになります。
+- pattern fill は foreground と background の2色を使えますが、`Style.Fill.Color` は1色だけです。両方あるときは foreground を保持し、background は再適用時に失われます。background のみある場合も API の再適用は foreground として出力します。
+- `Fill.Transparency` はセル style XML に保存されず、値を復元できません。
+- 未知の pattern ID と border style 名は公開列挙値へ写せないため 0 (`none`) として返します。auto 色、未知の色参照、palette / theme から解決できない色は空色になります。
+- `Border` には `outline`、`vertical`、`horizontal` の公開表現がありません。取得対象は `left`、`right`、`top`、`bottom`、`diagonalUp`、`diagonalDown` です。未対応の border style 名は `Style` 0 (`none`) に写ります。
+- `Font` の `Color` は auto 色を表現しません。`` は空色とし、再適用では自動色指定そのものを出力できません。黒を示す indexed 0 へ誤変換することはありません。theme / indexed の参照値は v2.10.1 で保持できますが、見た目を RGB 固定にしたい場合は `ColorIndexed` を -1、`ColorTheme` を nil、`ColorTint` を 0 にし、表示色を `Color` に指定します。参照 identity と見た目の固定は異なる選択です。同じ identity と見た目を保つテストでは、再適用先の theme / palette が元と同一であることを確認します。
+- `ColorIndexed` の zero 値は「未指定」と「index 0」を区別できません。実装は RGB、theme、auto がある場合は selector なしとし、index 単独の zero は index 0 として扱います。公開 API の型に状態を表す値がないため、明示された index 0 と selector 省略の両方を区別できません。
+- `formatCode16` は読み込み時に選択した書式コードを `CustomNumFmt` に保持します。`NewStyle` は通常の `formatCode` を出力するため、拡張属性そのものは再生成しません。decimal や `[Red]` を推測して誤るより、選択した完全なコードを保持します。
+- OOXML に複数の書式定義や named style があるときは、セルに適用された実効書式を返します。元の XF の構造や継承元の参照関係は保存しません。
+
+## 検証
+
+`style_roundtrip_test.go` のテストは v2.10.1 の40フィールド棚卸し、Font fieldごとの再適用、全 gradient preset、pattern 0〜18、border style 0〜13、theme/indexed identity と RGB、組み込み decimal 数、明示適用・継承および省略 ID による Font ID 0、空 boolean 属性、疎な border、pattern の2色制約、Alignment 全9属性、Protection の既定値・解除・継承を確認します。gradient、色参照、Alignment、Protection などの焦点項目は、独自 extractor の戻り値だけでなく、保存後の `xl/styles.xml` を XML として読み直して比較します。
+
+## 全フィールドの型付き定義と enum の更新
+
+`excelizestyle.StyleDefinition` と入れ子の定義は、依存中の Excelize の公開 Style 関連フィールドを全て保持します。罫線・塗り・配置・下線・色セレクタ・charset・数値書式・言語などの選択値には型付き enum を使い、任意の色・サイズ・文字列・数値と bool は元の型で保持します。`ToExcelize` と `StyleDefinitionFromExcelize` は全フィールドの相互変換を提供します。`GetStyleDefinition` はセルの取得結果をこの型付き定義で返します。元の Style 入力と workbook から復元できる値は異なり、上記の再適用制約は引き続き適用されます。
+
+`go generate ./excelizeutil` は、依存中の Excelize のソースを Go AST で解析し、公開 enum、全フィールド名 enum、型付き定義、相互変換、gradient geometry を生成します。罫線・pattern・gradient・数値書式などの定義追加は再生成で反映されます。配置の選択値は AST のドキュメントコメントを解析し、旧版の文書に欠けている OOXML の `general` と `bottom` を補います。Excelize が enum として定義していない reading order、theme slot、charset は OOXML の定義を明示します。任意値の領域を AST だけから推測して enum 化することはしません。
+
+依存更新後は生成を実行し、`(cd excelizeutil && go run ./cmd/gen-style-enums -check)` で生成物の更新漏れを確認してください。上流の構造変更・未知の gradient geometry は生成エラーになります。新規フィールドの定義と相互変換は自動で追加されますが、workbook 取得処理の対応可否は別途確認が必要です。使い方と生成範囲は [`excelizestyle/README.md`](../excelizestyle/README.md) に記載しています。
diff --git a/excelizeutil/cmd/gen-style-enums/additional.go b/excelizeutil/cmd/gen-style-enums/additional.go
new file mode 100644
index 0000000..f43f36b
--- /dev/null
+++ b/excelizeutil/cmd/gen-style-enums/additional.go
@@ -0,0 +1,628 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/format"
+ "go/parser"
+ "go/token"
+ "os"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+func saveGenerated(path string, content []byte) error {
+ formatted, err := format.Source(content)
+ if err != nil {
+ return fmt.Errorf("format %s: %w", path, err)
+ }
+ if *checkOutput {
+ current, err := os.ReadFile(path)
+ if err != nil {
+ return err
+ }
+ if !bytes.Equal(current, formatted) {
+ return fmt.Errorf("%s is stale; run go generate ./excelizeutil", path)
+ }
+ return nil
+ }
+ return os.WriteFile(path, formatted, 0o644)
+}
+
+func expressionText(expr ast.Expr) string {
+ var b bytes.Buffer
+ _ = format.Node(&b, token.NewFileSet(), expr)
+ return b.String()
+}
+
+func initializer(file *ast.File, name string) ast.Expr {
+ var result ast.Expr
+ ast.Inspect(file, func(n ast.Node) bool {
+ if result != nil {
+ return false
+ }
+ switch node := n.(type) {
+ case *ast.ValueSpec:
+ for i, id := range node.Names {
+ if id.Name == name && i < len(node.Values) {
+ result = node.Values[i]
+ }
+ }
+ case *ast.AssignStmt:
+ for i, lhs := range node.Lhs {
+ if id, ok := lhs.(*ast.Ident); ok && id.Name == name && i < len(node.Rhs) {
+ result = node.Rhs[i]
+ }
+ }
+ }
+ return true
+ })
+ return result
+}
+
+func stringLiteral(expr ast.Expr) (string, error) {
+ v, ok := expr.(*ast.BasicLit)
+ if !ok || v.Kind != token.STRING {
+ return "", fmt.Errorf("expected string literal: %s", expressionText(expr))
+ }
+ return strconv.Unquote(v.Value)
+}
+
+func stringSwitchValues(file *ast.File, tag string) ([]string, error) {
+ var values []string
+ var failure error
+ ast.Inspect(file, func(n ast.Node) bool {
+ sw, ok := n.(*ast.SwitchStmt)
+ if !ok || sw.Tag == nil || !strings.HasSuffix(expressionText(sw.Tag), tag) {
+ return true
+ }
+ for _, statement := range sw.Body.List {
+ c := statement.(*ast.CaseClause)
+ for _, expr := range c.List {
+ value, err := stringLiteral(expr)
+ if err != nil {
+ failure = err
+ return false
+ }
+ values = appendUnique(values, value)
+ }
+ }
+ return false
+ })
+ if failure != nil {
+ return nil, failure
+ }
+ if len(values) == 0 {
+ return nil, fmt.Errorf("cannot locate string switch %s", tag)
+ }
+ return values, nil
+}
+
+func appendUnique(values []string, value string) []string {
+ for _, existing := range values {
+ if existing == value {
+ return values
+ }
+ }
+ return append(values, value)
+}
+
+// Alignment has no validation table in Excelize's implementation. Its documented
+// choices live in NewStyle's AST comment; general/bottom are OOXML defaults that
+// older Excelize documentation omits.
+func alignmentOptions(file *ast.File, axis string) ([]string, error) {
+ for _, group := range file.Comments {
+ lines := strings.Split(group.Text(), "\n")
+ for i, line := range lines {
+ if !strings.Contains(line, axis+" alignment") {
+ continue
+ }
+ var values []string
+ for _, row := range lines[i+1:] {
+ text := strings.TrimSpace(row)
+ if len(values) > 0 && text == "" {
+ break
+ }
+ if text == "" || text == "Style" || strings.HasPrefix(text, "--") {
+ continue
+ }
+ if strings.ContainsAny(text, " :|'().,\t") {
+ continue
+ }
+ if _, err := enumIdentifier(text); err == nil {
+ values = appendUnique(values, text)
+ }
+ }
+ if len(values) > 0 {
+ return values, nil
+ }
+ }
+ }
+ return nil, fmt.Errorf("cannot locate documented %s alignment choices", axis)
+}
+
+func writeStringEnum(out *bytes.Buffer, name string, values []string) error {
+ fmt.Fprintf(out, "type %s string\n\nconst (\n", name)
+ seen := map[string]bool{}
+ for _, value := range values {
+ suffix := "Unset"
+ var err error
+ if value != "" {
+ suffix, err = enumIdentifier(strings.ReplaceAll(value, "-", "_"))
+ }
+ if err != nil {
+ return err
+ }
+ if seen[suffix] {
+ return fmt.Errorf("duplicate %s constant %s", name, suffix)
+ }
+ seen[suffix] = true
+ fmt.Fprintf(out, "%s%s %s = %q\n", name, suffix, name, value)
+ }
+ fmt.Fprintln(out, ")")
+ fmt.Fprintf(out, "\nfunc %sValues() []%s { return []%s{", name, name, name)
+ for _, value := range values {
+ fmt.Fprintf(out, "%q,", value)
+ }
+ out.WriteString("} }\n\n")
+ return nil
+}
+
+func additionalEnums(dir string, styles *ast.File, specs []enumSpec) ([]byte, []byte, error) {
+ var public bytes.Buffer
+ public.WriteString("// Code generated by go generate ./excelizeutil; DO NOT EDIT.\n\npackage excelizestyle\n\nimport \"github.com/xuri/excelize/v2\"\n\n")
+ for _, spec := range specs {
+ values, err := findEnumValues(styles, spec)
+ if err != nil {
+ return nil, nil, err
+ }
+ spec.typeName = strings.ToUpper(spec.typeName[:1]) + spec.typeName[1:]
+ spec.constantPrefix = spec.typeName
+ if err := writeEnum(&public, spec, values); err != nil {
+ return nil, nil, err
+ }
+ }
+ positions, err := stringSwitchValues(styles, "v.Type")
+ if expr := initializer(styles, "styleBorderTypes"); expr != nil {
+ positions, err = stringValues(expr, "styleBorderTypes")
+ }
+ if err != nil {
+ return nil, nil, err
+ }
+ fillTypes, err := stringSwitchValues(styles, ".Fill.Type")
+ if err != nil {
+ return nil, nil, err
+ }
+ horizontal, err := alignmentOptions(styles, "horizontal")
+ if err != nil {
+ return nil, nil, err
+ }
+ vertical, err := alignmentOptions(styles, "vertical")
+ if err != nil {
+ return nil, nil, err
+ }
+ horizontal = appendUnique(horizontal, "general")
+ vertical = appendUnique(vertical, "bottom")
+ underlineExpr := initializer(styles, "fontUnderlineType")
+ underline := []string{}
+ template, err := parser.ParseFile(token.NewFileSet(), filepath.Join(dir, "templates.go"), nil, 0)
+ if err != nil {
+ return nil, nil, err
+ }
+ if expr := initializer(template, "supportedUnderlineTypes"); expr != nil {
+ underline, err = stringValues(expr, "supportedUnderlineTypes")
+ } else if literal, ok := underlineExpr.(*ast.CompositeLit); ok {
+ for _, e := range literal.Elts {
+ value, e := stringLiteral(e.(*ast.KeyValueExpr).Key)
+ if e != nil {
+ return nil, nil, e
+ }
+ underline = append(underline, value)
+ }
+ } else {
+ return nil, nil, fmt.Errorf("cannot locate underline choices")
+ }
+ if err != nil {
+ return nil, nil, err
+ }
+ // An empty underline/fill represents an unset value and must remain expressible.
+ fillTypes = appendUnique(fillTypes, "")
+ underline = appendUnique(underline, "")
+ vertAlign := []string{"baseline", "superscript", "subscript"}
+ ast.Inspect(styles, func(n ast.Node) bool {
+ call, ok := n.(*ast.CallExpr)
+ if !ok || len(call.Args) < 2 || !strings.HasSuffix(expressionText(call.Args[1]), ".VertAlign") {
+ return true
+ }
+ if _, ok := call.Args[0].(*ast.CompositeLit); ok {
+ values, e := stringValues(call.Args[0], "VertAlign")
+ if e == nil {
+ vertAlign = values
+ }
+ }
+ return true
+ })
+ for _, spec := range []struct {
+ name string
+ values []string
+ }{
+ {"BorderPosition", positions}, {"FillType", fillTypes},
+ {"AlignmentHorizontal", horizontal}, {"AlignmentVertical", vertical},
+ {"FontUnderline", underline}, {"FontVerticalAlign", vertAlign},
+ } {
+ if err := writeStringEnum(&public, spec.name, spec.values); err != nil {
+ return nil, nil, err
+ }
+ }
+ public.WriteString("type AlignmentReadingOrder uint64\nconst (AlignmentReadingOrderContext AlignmentReadingOrder = iota; AlignmentReadingOrderLeftToRight; AlignmentReadingOrderRightToLeft)\n\n")
+ numberSource := styles
+ if initializer(styles, "builtInNumFmt") == nil {
+ numberSource, err = parser.ParseFile(token.NewFileSet(), filepath.Join(dir, "numfmt.go"), nil, 0)
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+ if err := numberAndLanguageEnums(&public, numberSource); err != nil {
+ return nil, nil, err
+ }
+ if err := fieldEnums(&public, dir); err != nil {
+ return nil, nil, err
+ }
+ if err := colorEnums(&public, template); err != nil {
+ return nil, nil, err
+ }
+ if err := typedDefinitions(&public, dir); err != nil {
+ return nil, nil, err
+ }
+ presets, err := gradientPresets(styles)
+ if err != nil {
+ return nil, nil, err
+ }
+ fmt.Fprintln(&public, "type GradientShading int\nconst (")
+ for i, preset := range presets {
+ kind := preset.kind
+ if kind == "" {
+ kind = "linear"
+ }
+ fmt.Fprintf(&public, "// GradientShadingPreset%d selects preset %d: %s gradient, degree %g, path bounds (left %g, right %g, top %g, bottom %g), and stop positions [%s].\n//\n// See %s\n", i, i, kind, preset.degree, preset.left, preset.right, preset.top, preset.bottom, numbers(preset.stops), officialStyleDocs)
+ fmt.Fprintf(&public, "GradientShadingPreset%d GradientShading = %d\n", i, i)
+ }
+ fmt.Fprintf(&public, "GradientShadingCount GradientShading = %d\n)\n", len(presets))
+ var geometry bytes.Buffer
+ fmt.Fprintln(&geometry, "func gradientGeometries() []gradientGeometry { return []gradientGeometry{")
+ for _, preset := range presets {
+ fmt.Fprintf(&geometry, "{typeName:%q,degree:%g,left:%g,right:%g,top:%g,bottom:%g,positions:[]float64{%s}},\n", preset.kind, preset.degree, preset.left, preset.right, preset.top, preset.bottom, numbers(preset.stops))
+ }
+ fmt.Fprintln(&geometry, "} }")
+ return public.Bytes(), geometry.Bytes(), nil
+}
+
+func numberAndLanguageEnums(out *bytes.Buffer, styles *ast.File) error {
+ values := map[int]string{}
+ allIDs := map[int]bool{}
+ for _, name := range []string{"builtInNumFmt", "currencyNumFmt"} {
+ formats, ok := initializer(styles, name).(*ast.CompositeLit)
+ if !ok {
+ return fmt.Errorf("cannot locate %s", name)
+ }
+ for _, item := range formats.Elts {
+ kv, ok := item.(*ast.KeyValueExpr)
+ if !ok {
+ return fmt.Errorf("unexpected number format entry")
+ }
+ id, err := strconv.Atoi(expressionText(kv.Key))
+ if err != nil {
+ return err
+ }
+ code, err := stringLiteral(kv.Value)
+ if err != nil {
+ return err
+ }
+ values[id] = code
+ allIDs[id] = true
+ }
+ }
+ languages, ok := initializer(styles, "langNumFmt").(*ast.CompositeLit)
+ if !ok {
+ return fmt.Errorf("cannot locate langNumFmt")
+ }
+ languageFormats := map[string]map[int]string{}
+ for _, item := range languages.Elts {
+ kv := item.(*ast.KeyValueExpr)
+ code, err := stringLiteral(kv.Key)
+ if err != nil {
+ return err
+ }
+ formats, ok := kv.Value.(*ast.CompositeLit)
+ if !ok {
+ return fmt.Errorf("unexpected language formats")
+ }
+ languageFormats[code] = map[int]string{}
+ for _, item := range formats.Elts {
+ kv := item.(*ast.KeyValueExpr)
+ id, err := strconv.Atoi(expressionText(kv.Key))
+ if err != nil {
+ return err
+ }
+ value, err := stringLiteral(kv.Value)
+ if err != nil {
+ return err
+ }
+ languageFormats[code][id] = value
+ allIDs[id] = true
+ }
+ }
+ ids := []int{}
+ for id := range allIDs {
+ ids = append(ids, id)
+ }
+ sort.Ints(ids)
+ fmt.Fprintln(out, "type NumberFormat int\nconst (")
+ for _, id := range ids {
+ fmt.Fprintf(out, "NumberFormatID%d NumberFormat = %d\n", id, id)
+ }
+ fmt.Fprintln(out, ")\n\nfunc (value NumberFormat) Code() (string,bool) { switch value {")
+ for _, id := range ids {
+ if code, ok := values[id]; ok {
+ fmt.Fprintf(out, "case NumberFormatID%d: return %q,true\n", id, code)
+ }
+ }
+ out.WriteString("default:return \"\",false\n} }\n\n")
+ var codes []string
+ for code := range languageFormats {
+ codes = append(codes, code)
+ }
+ sort.Strings(codes)
+ if err := writeStringEnum(out, "StyleLanguage", codes); err != nil {
+ return err
+ }
+ fmt.Fprintln(out, "func (value NumberFormat) CodeForLanguage(language StyleLanguage) (string, bool) { switch language {")
+ for _, code := range codes {
+ fmt.Fprintf(out, "case %q: switch value {\n", code)
+ for _, id := range ids {
+ if value, ok := languageFormats[code][id]; ok {
+ fmt.Fprintf(out, "case NumberFormatID%d: return %q,true\n", id, value)
+ }
+ }
+ fmt.Fprintln(out, "}")
+ }
+ fmt.Fprintln(out, "}; return value.Code()\n}")
+ return nil
+}
+
+func fieldEnums(out *bytes.Buffer, dir string) error {
+ file, err := parser.ParseFile(token.NewFileSet(), filepath.Join(dir, "xmlStyles.go"), nil, 0)
+ if err != nil {
+ return err
+ }
+ wanted := map[string]bool{"Style": true, "Border": true, "Fill": true, "Font": true, "Alignment": true, "Protection": true}
+ found := map[string]bool{}
+ for _, decl := range file.Decls {
+ group, ok := decl.(*ast.GenDecl)
+ if !ok {
+ continue
+ }
+ for _, s := range group.Specs {
+ spec, ok := s.(*ast.TypeSpec)
+ if !ok || !wanted[spec.Name.Name] {
+ continue
+ }
+ structure, ok := spec.Type.(*ast.StructType)
+ if !ok {
+ return fmt.Errorf("%s is no longer a struct", spec.Name.Name)
+ }
+ var fields []string
+ for _, field := range structure.Fields.List {
+ for _, name := range field.Names {
+ if name.IsExported() {
+ fields = append(fields, name.Name)
+ }
+ }
+ }
+ if err := writeStringEnum(out, spec.Name.Name+"Field", fields); err != nil {
+ return err
+ }
+ found[spec.Name.Name] = true
+ }
+ }
+ if len(found) != len(wanted) {
+ return fmt.Errorf("one or more public Style types are missing")
+ }
+ return nil
+}
+
+type gradientPreset struct {
+ kind string
+ degree, left, right, top, bottom float64
+ stops []float64
+}
+
+func numbers(values []float64) string {
+ var parts []string
+ for _, v := range values {
+ parts = append(parts, strconv.FormatFloat(v, 'g', -1, 64))
+ }
+ return strings.Join(parts, ",")
+}
+func numeric(expr ast.Expr) (float64, error) { return strconv.ParseFloat(expressionText(expr), 64) }
+func gradientPresets(styles *ast.File) ([]gradientPreset, error) {
+ if expr := initializer(styles, "styleFillVariants"); expr != nil {
+ fn, ok := expr.(*ast.FuncLit)
+ if !ok {
+ call, called := expr.(*ast.CallExpr)
+ if called {
+ fn, ok = call.Fun.(*ast.FuncLit)
+ }
+ }
+ if !ok {
+ return nil, fmt.Errorf("unexpected styleFillVariants initializer")
+ }
+ var literals *ast.CompositeLit
+ for _, stmt := range fn.Body.List {
+ if ret, ok := stmt.(*ast.ReturnStmt); ok && len(ret.Results) == 1 {
+ literals, _ = ret.Results[0].(*ast.CompositeLit)
+ }
+ }
+ if literals == nil {
+ return nil, fmt.Errorf("missing gradient return literal")
+ }
+ var values []gradientPreset
+ for _, expr := range literals.Elts {
+ literal, ok := expr.(*ast.CompositeLit)
+ if !ok {
+ return nil, fmt.Errorf("unexpected gradient preset")
+ }
+ p := gradientPreset{}
+ for _, item := range literal.Elts {
+ kv, ok := item.(*ast.KeyValueExpr)
+ if !ok {
+ return nil, fmt.Errorf("unexpected gradient field")
+ }
+ name := expressionText(kv.Key)
+ switch name {
+ case "Type":
+ v, err := stringLiteral(kv.Value)
+ if err != nil {
+ return nil, err
+ }
+ p.kind = v
+ case "Stop":
+ stops, ok := kv.Value.(*ast.CompositeLit)
+ if !ok {
+ return nil, fmt.Errorf("unexpected gradient stops")
+ }
+ for _, expr := range stops.Elts {
+ stop, ok := expr.(*ast.CompositeLit)
+ if !ok {
+ return nil, fmt.Errorf("unexpected gradient stop")
+ }
+ position := float64(0)
+ for _, item := range stop.Elts {
+ kv := item.(*ast.KeyValueExpr)
+ if expressionText(kv.Key) != "Position" {
+ return nil, fmt.Errorf("unsupported gradient stop field")
+ }
+ var err error
+ position, err = numeric(kv.Value)
+ if err != nil {
+ return nil, err
+ }
+ }
+ p.stops = append(p.stops, position)
+ }
+ default:
+ if err := setGeometry(&p, name, kv.Value); err != nil {
+ return nil, err
+ }
+ }
+ }
+ if len(p.stops) < 2 || len(p.stops) > 3 {
+ return nil, fmt.Errorf("gradient stop count is not representable by the two-color API")
+ }
+ values = append(values, p)
+ }
+ return values, nil
+ }
+ // Excelize v2.6 builds presets with a switch and a degree lookup slice.
+ twoColors, indexedPositions := false, false
+ ast.Inspect(styles, func(n ast.Node) bool {
+ if node, ok := n.(*ast.IfStmt); ok && expressionText(node.Cond) == "len(style.Fill.Color) != 2" {
+ twoColors = true
+ }
+ if node, ok := n.(*ast.AssignStmt); ok && len(node.Lhs) == 1 && len(node.Rhs) == 1 && expressionText(node.Lhs[0]) == "stop.Position" && expressionText(node.Rhs[0]) == "float64(index)" {
+ indexedPositions = true
+ }
+ return true
+ })
+ if !twoColors || !indexedPositions {
+ return nil, fmt.Errorf("unsupported legacy gradient stop construction")
+ }
+ variants, ok := initializer(styles, "variants").(*ast.CompositeLit)
+ if !ok {
+ return nil, fmt.Errorf("cannot locate legacy gradient variants")
+ }
+ var sw *ast.SwitchStmt
+ ast.Inspect(styles, func(n ast.Node) bool {
+ if v, ok := n.(*ast.SwitchStmt); ok && v.Tag != nil && strings.HasSuffix(expressionText(v.Tag), ".Fill.Shading") {
+ sw = v
+ return false
+ }
+ return true
+ })
+ if sw == nil {
+ return nil, fmt.Errorf("cannot locate legacy shading switch")
+ }
+ indexed := map[int]gradientPreset{}
+ for _, stmt := range sw.Body.List {
+ c := stmt.(*ast.CaseClause)
+ for _, expr := range c.List {
+ id, err := strconv.Atoi(expressionText(expr))
+ if err != nil {
+ return nil, err
+ }
+ p := gradientPreset{stops: []float64{0, 1}}
+ for _, stmt := range c.Body {
+ a, ok := stmt.(*ast.AssignStmt)
+ if !ok || len(a.Lhs) != 1 || len(a.Rhs) != 1 {
+ return nil, fmt.Errorf("unsupported legacy gradient statement")
+ }
+ lhs, ok := a.Lhs[0].(*ast.SelectorExpr)
+ if !ok || expressionText(lhs.X) != "gradient" {
+ return nil, fmt.Errorf("unsupported legacy gradient assignment")
+ }
+ switch lhs.Sel.Name {
+ case "Type":
+ p.kind, err = stringLiteral(a.Rhs[0])
+ case "Degree":
+ if index, ok := a.Rhs[0].(*ast.IndexExpr); ok && expressionText(index.X) == "variants" {
+ if id >= len(variants.Elts) {
+ return nil, fmt.Errorf("gradient index out of range")
+ }
+ p.degree, err = numeric(variants.Elts[id])
+ } else {
+ err = setGeometry(&p, "Degree", a.Rhs[0])
+ }
+ default:
+ err = setGeometry(&p, lhs.Sel.Name, a.Rhs[0])
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+ indexed[id] = p
+ }
+ }
+ values := make([]gradientPreset, len(indexed))
+ for i := range values {
+ p, ok := indexed[i]
+ if !ok {
+ return nil, fmt.Errorf("non-contiguous gradient preset IDs")
+ }
+ values[i] = p
+ }
+ return values, nil
+}
+func setGeometry(p *gradientPreset, name string, value ast.Expr) error {
+ n, err := numeric(value)
+ if err != nil {
+ return err
+ }
+ switch name {
+ case "Degree":
+ p.degree = n
+ case "Left":
+ p.left = n
+ case "Right":
+ p.right = n
+ case "Top":
+ p.top = n
+ case "Bottom":
+ p.bottom = n
+ default:
+ return fmt.Errorf("unknown gradient field %s", name)
+ }
+ return nil
+}
diff --git a/excelizeutil/cmd/gen-style-enums/additional_test.go b/excelizeutil/cmd/gen-style-enums/additional_test.go
new file mode 100644
index 0000000..cedb3a2
--- /dev/null
+++ b/excelizeutil/cmd/gen-style-enums/additional_test.go
@@ -0,0 +1,132 @@
+package main
+
+import (
+ "bytes"
+ "go/parser"
+ "go/token"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+)
+
+const fixtureStyles = `package excelize
+var styleFillPatterns = []string{"none", "newPattern"}
+var styleBorders = []string{"none", "newBorder"}
+var styleBorderTypes = []string{"left", "diagonalUp"}
+var builtInNumFmt = map[int]string{0:"general", 14:"mm-dd-yy"}
+var currencyNumFmt = map[int]string{164:"currency-code"}
+var langNumFmt = map[string]map[int]string{"ja-jp":{27:"localized-code"}}
+var styleFillVariants = func() []xlsxGradientFill { return []xlsxGradientFill{
+ {Degree:111, Stop:[]*xlsxGradientFillStop{{}, {Position:0.5}, {Position:1}}},
+ {Type:"path", Left:0.5, Stop:[]*xlsxGradientFillStop{{}, {Position:1}}},
+} }
+// The following the type of horizontal alignment in cells:
+//
+// Style
+// -----
+// left
+// newHorizontal
+//
+// The following the type of vertical alignment in cells:
+//
+// Style
+// -----
+// top
+// newVertical
+//
+func NewStyle() {}
+func newFills(style Style) {switch style.Fill.Type {case "gradient":case "pattern":}}
+`
+const fixtureTypes = `package excelize
+type Border struct {Type string; Color string; Style int}
+type Fill struct {Type string; Pattern int; Color []string; Shading int}
+type Font struct {Bold bool; Underline string; NewFlag bool}
+type Alignment struct {Horizontal string; Vertical string; ReadingOrder uint64}
+type Protection struct {Locked bool; Hidden bool}
+type Style struct {Border []Border; Fill Fill; Font *Font; Alignment *Alignment; Protection *Protection; NumFmt int; NewValue string}
+`
+
+func TestGenerationTracksNewFieldsValuesAndGradientPresets(t *testing.T) {
+ dir := t.TempDir()
+ for name, content := range map[string]string{"xmlStyles.go": fixtureTypes, "templates.go": `package excelize; var supportedUnderlineTypes=[]string{"none","single","double","newUnderline"}`} {
+ if err := os.WriteFile(filepath.Join(dir, name), []byte(content), 0600); err != nil {
+ t.Fatal(err)
+ }
+ }
+ file, err := parser.ParseFile(token.NewFileSet(), "styles.go", fixtureStyles, parser.ParseComments)
+ if err != nil {
+ t.Fatal(err)
+ }
+ specs := []enumSpec{{typeName: "fillPattern", constantPrefix: "fillPattern", packageVar: "styleFillPatterns"}, {typeName: "borderStyle", constantPrefix: "borderStyle", packageVar: "styleBorders"}}
+ public, geometry, err := additionalEnums(dir, file, specs)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, fragment := range []string{"FillPatternNewPattern", "BorderStyleNewBorder", "AlignmentHorizontalNewHorizontal", "FontUnderlineNewUnderline", "FontFieldNewFlag", "StyleFieldNewValue", "out.NewValue = in.NewValue", "NumberFormatID164", "NumberFormatID27", "GradientShadingPreset1"} {
+ if !strings.Contains(string(public), fragment) {
+ t.Errorf("generated output does not track upstream addition %q", fragment)
+ }
+ }
+ if !bytes.Contains(geometry, []byte("degree:111")) || !bytes.Contains(geometry, []byte("0,0.5,1")) {
+ t.Fatalf("gradient geometry was not derived from source: %s", geometry)
+ }
+ if _, err := parser.ParseFile(token.NewFileSet(), "generated.go", public, 0); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestUnknownGradientGeometryFailsGeneration(t *testing.T) {
+ source := strings.Replace(fixtureStyles, "Degree:111", "NewGeometry:111", 1)
+ file, err := parser.ParseFile(token.NewFileSet(), "styles.go", source, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := gradientPresets(file); err == nil {
+ t.Fatal("unknown gradient field was silently ignored")
+ }
+}
+
+func TestCheckReportsStaleOutputWithoutWriting(t *testing.T) {
+ old := *checkOutput
+ *checkOutput = true
+ defer func() { *checkOutput = old }()
+ path := filepath.Join(t.TempDir(), "generated.go")
+ original := []byte("package stale\n")
+ if err := os.WriteFile(path, original, 0600); err != nil {
+ t.Fatal(err)
+ }
+ if err := saveGenerated(path, []byte("package updated\n")); err == nil {
+ t.Fatal("stale generated file accepted")
+ }
+ got, err := os.ReadFile(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(got, original) {
+ t.Fatal("check mode modified a file")
+ }
+}
+
+func TestGeneratedFilesMatchSelectedDependency(t *testing.T) {
+ dir, err := excelizeModuleDir()
+ if err != nil {
+ t.Fatal(err)
+ }
+ public, private, err := generatedSources(dir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for path, expected := range map[string][]byte{
+ "../../../excelizestyle/style_enums_gen.go": public,
+ "../../style_enums_gen.go": private,
+ } {
+ actual, err := os.ReadFile(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(actual, expected) {
+ t.Errorf("%s is stale for the selected Excelize dependency; run go generate ./excelizeutil", path)
+ }
+ }
+}
diff --git a/excelizeutil/cmd/gen-style-enums/colors.go b/excelizeutil/cmd/gen-style-enums/colors.go
new file mode 100644
index 0000000..fb08554
--- /dev/null
+++ b/excelizeutil/cmd/gen-style-enums/colors.go
@@ -0,0 +1,40 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+)
+
+// These identifiers are defined by OOXML, not by a closed enum in Excelize.
+// Arbitrary underlying values remain expressible for future/custom definitions.
+func colorEnums(out *bytes.Buffer, templates *ast.File) error {
+ paletteSize := 64
+ if expr := initializer(templates, "IndexedColorMapping"); expr != nil {
+ colors, err := stringValues(expr, "IndexedColorMapping")
+ if err != nil {
+ return err
+ }
+ paletteSize = len(colors)
+ }
+ fmt.Fprintln(out, "type IndexedColor int\nconst (\nIndexedColorUnset IndexedColor = -1")
+ for i := 0; i < paletteSize; i++ {
+ fmt.Fprintf(out, "IndexedColorIndex%d IndexedColor = %d\n", i, i)
+ }
+ fmt.Fprintf(out, "IndexedColorSystemForeground IndexedColor = %d\nIndexedColorSystemBackground IndexedColor = %d\n)\n", 64, 65)
+ fmt.Fprintln(out, "type ThemeColor int\nconst (")
+ for i, name := range []string{"Light1", "Dark1", "Light2", "Dark2", "Accent1", "Accent2", "Accent3", "Accent4", "Accent5", "Accent6", "Hyperlink", "FollowedHyperlink"} {
+ fmt.Fprintf(out, "ThemeColor%s ThemeColor = %d\n", name, i)
+ }
+ fmt.Fprintln(out, ")\ntype FontCharset int\nconst (")
+ for _, v := range []struct {
+ name string
+ id int
+ }{
+ {"ANSI", 0}, {"Default", 1}, {"Symbol", 2}, {"Mac", 77}, {"ShiftJIS", 128}, {"Hangul", 129}, {"Johab", 130}, {"GB2312", 134}, {"Big5", 136}, {"Greek", 161}, {"Turkish", 162}, {"Vietnamese", 163}, {"Hebrew", 177}, {"Arabic", 178}, {"Baltic", 186}, {"Russian", 204}, {"Thai", 222}, {"EastEurope", 238}, {"OEM", 255},
+ } {
+ fmt.Fprintf(out, "FontCharset%s FontCharset = %d\n", v.name, v.id)
+ }
+ fmt.Fprintln(out, ")")
+ return nil
+}
diff --git a/excelizeutil/cmd/gen-style-enums/definitions.go b/excelizeutil/cmd/gen-style-enums/definitions.go
new file mode 100644
index 0000000..19afac4
--- /dev/null
+++ b/excelizeutil/cmd/gen-style-enums/definitions.go
@@ -0,0 +1,151 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "path/filepath"
+ "strings"
+)
+
+var definitionTypes = map[string]bool{"Style": true, "Border": true, "Fill": true, "Font": true, "Alignment": true, "Protection": true}
+var enumFields = map[string]string{
+ "Border.Type": "BorderPosition", "Border.Style": "BorderStyle",
+ "Fill.Type": "FillType", "Fill.Pattern": "FillPattern", "Fill.Shading": "GradientShading",
+ "Font.Underline": "FontUnderline", "Font.VertAlign": "FontVerticalAlign",
+ "Font.ColorIndexed": "IndexedColor", "Font.ColorTheme": "*ThemeColor", "Font.Charset": "*FontCharset",
+ "Alignment.Horizontal": "AlignmentHorizontal", "Alignment.Vertical": "AlignmentVertical", "Alignment.ReadingOrder": "AlignmentReadingOrder",
+ "Style.NumFmt": "NumberFormat", "Style.Lang": "StyleLanguage",
+}
+
+func typedDefinitions(out *bytes.Buffer, dir string) error {
+ file, err := parser.ParseFile(token.NewFileSet(), filepath.Join(dir, "xmlStyles.go"), nil, 0)
+ if err != nil {
+ return err
+ }
+ for _, decl := range file.Decls {
+ group, ok := decl.(*ast.GenDecl)
+ if !ok {
+ continue
+ }
+ for _, raw := range group.Specs {
+ spec, ok := raw.(*ast.TypeSpec)
+ if !ok || !definitionTypes[spec.Name.Name] {
+ continue
+ }
+ structure, ok := spec.Type.(*ast.StructType)
+ if !ok {
+ return fmt.Errorf("%s is no longer a struct", spec.Name.Name)
+ }
+ name := spec.Name.Name
+ fmt.Fprintf(out, "// %sDefinition preserves all public excelize.%s fields with typed categorical values.\ntype %sDefinition struct {\n", name, name, name)
+ for _, field := range structure.Fields.List {
+ for _, id := range field.Names {
+ if !id.IsExported() {
+ continue
+ }
+ kind := definitionFieldType(field.Type)
+ if enum, ok := enumFields[name+"."+id.Name]; ok {
+ kind = enum
+ }
+ fmt.Fprintf(out, "%s %s\n", id.Name, kind)
+ }
+ }
+ fmt.Fprintln(out, "}")
+ for _, reverse := range []bool{false, true} {
+ if reverse {
+ fmt.Fprintf(out, "func %sDefinitionFromExcelize(in excelize.%s) %sDefinition {\n out := %sDefinition{}\n", name, name, name, name)
+ } else {
+ fmt.Fprintf(out, "func (in %sDefinition) ToExcelize() excelize.%s {\n out := excelize.%s{}\n", name, name, name)
+ }
+ for _, field := range structure.Fields.List {
+ for _, id := range field.Names {
+ if id.IsExported() {
+ writeConversion(out, name, id.Name, field.Type, reverse)
+ }
+ }
+ }
+ fmt.Fprintln(out, "return out\n}")
+ }
+ }
+ }
+ return nil
+}
+
+func definitionFieldType(expr ast.Expr) string {
+ switch t := expr.(type) {
+ case *ast.Ident:
+ if definitionTypes[t.Name] {
+ return t.Name + "Definition"
+ }
+ switch t.Name {
+ case "bool", "int", "uint64", "float64", "string":
+ return t.Name
+ default:
+ return "excelize." + t.Name
+ }
+ case *ast.StarExpr:
+ return "*" + definitionFieldType(t.X)
+ case *ast.ArrayType:
+ if t.Len == nil {
+ return "[]" + definitionFieldType(t.Elt)
+ }
+ }
+ return expressionText(expr)
+}
+
+func writeConversion(out *bytes.Buffer, owner, field string, expr ast.Expr, reverse bool) {
+ if enum, ok := enumFields[owner+"."+field]; ok {
+ if pointer, ok := expr.(*ast.StarExpr); ok {
+ cast := expressionText(pointer.X)
+ if reverse {
+ cast = strings.TrimPrefix(enum, "*")
+ }
+ fmt.Fprintf(out, "if in.%s != nil { value := %s(*in.%s); out.%s = &value }\n", field, cast, field, field)
+ return
+ }
+ cast := expressionText(expr)
+ if reverse {
+ cast = enum
+ }
+ fmt.Fprintf(out, "out.%s = %s(in.%s)\n", field, cast, field)
+ return
+ }
+ if id, ok := expr.(*ast.Ident); ok && definitionTypes[id.Name] {
+ if reverse {
+ fmt.Fprintf(out, "out.%s = %sDefinitionFromExcelize(in.%s)\n", field, id.Name, field)
+ } else {
+ fmt.Fprintf(out, "out.%s = in.%s.ToExcelize()\n", field, field)
+ }
+ return
+ }
+ if ptr, ok := expr.(*ast.StarExpr); ok {
+ if id, ok := ptr.X.(*ast.Ident); ok && definitionTypes[id.Name] {
+ if reverse {
+ fmt.Fprintf(out, "if in.%s != nil { value := %sDefinitionFromExcelize(*in.%s); out.%s = &value }\n", field, id.Name, field, field)
+ } else {
+ fmt.Fprintf(out, "if in.%s != nil { value := in.%s.ToExcelize(); out.%s = &value }\n", field, field, field)
+ }
+ return
+ }
+ }
+ if slice, ok := expr.(*ast.ArrayType); ok && slice.Len == nil {
+ if id, ok := slice.Elt.(*ast.Ident); ok && definitionTypes[id.Name] {
+ kind := "excelize." + id.Name
+ if reverse {
+ kind = id.Name + "Definition"
+ }
+ fmt.Fprintf(out, "if in.%s != nil { out.%s = make([]%s,len(in.%s)); for i, value := range in.%s {", field, field, kind, field, field)
+ if reverse {
+ fmt.Fprintf(out, "out.%s[i] = %sDefinitionFromExcelize(value)", field, id.Name)
+ } else {
+ fmt.Fprintf(out, "out.%s[i] = value.ToExcelize()", field)
+ }
+ fmt.Fprintln(out, "} }")
+ return
+ }
+ }
+ fmt.Fprintf(out, "out.%s = in.%s\n", field, field)
+}
diff --git a/excelizeutil/cmd/gen-style-enums/godoc.go b/excelizeutil/cmd/gen-style-enums/godoc.go
new file mode 100644
index 0000000..7127bdd
--- /dev/null
+++ b/excelizeutil/cmd/gen-style-enums/godoc.go
@@ -0,0 +1,237 @@
+package main
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+const officialStyleDocs = "https://xuri.me/excelize/en/style.html"
+
+type enumDocumentation struct{ description, section string }
+
+var enumDocs = map[string]enumDocumentation{
+ "FillPattern": {"selects the pattern index used by excelize.Fill.Pattern", "pattern"},
+ "BorderStyle": {"selects the line style index used by excelize.Border.Style", "border"},
+ "BorderPosition": {"selects the edge or diagonal used by excelize.Border.Type", "border"},
+ "FillType": {"selects pattern or gradient filling for excelize.Fill.Type; the empty value leaves the fill unset", "fill"},
+ "AlignmentHorizontal": {"selects horizontal cell alignment, including general alignment", "align"},
+ "AlignmentVertical": {"selects vertical cell alignment, including bottom alignment", "align"},
+ "AlignmentReadingOrder": {"selects context-dependent, left-to-right, or right-to-left cell text direction", "align"},
+ "FontUnderline": {"selects the underline mode accepted by the selected Excelize dependency; the empty value leaves it unset", "underline"},
+ "FontVerticalAlign": {"selects baseline, superscript, or subscript placement of font text", ""},
+ "NumberFormat": {"selects an Excelize number-format ID; Code and CodeForLanguage resolve the dependency's format tables, not custom workbook definitions", "number_format"},
+ "StyleLanguage": {"identifies a language tag in Excelize's localized number-format tables; newer Style APIs use the resolved format code", "number_format"},
+ "GradientShading": {"selects a gradient preset in the selected Excelize dependency; preset numbering may change between versions", "shading"},
+ "IndexedColor": {"selects an indexed palette entry or system color for excelize.Font.ColorIndexed; workbook palettes can override the displayed RGB", ""},
+ "ThemeColor": {"selects a workbook theme slot for excelize.Font.ColorTheme; its displayed color depends on the workbook theme", ""},
+ "FontCharset": {"identifies an OOXML font character set for excelize.Font.Charset; these numeric selectors are not RGB colors or text encodings to apply to cell values", ""},
+}
+
+func enumDoc(name string) enumDocumentation {
+ if doc, ok := enumDocs[name]; ok {
+ return doc
+ }
+ if strings.HasSuffix(name, "Field") {
+ owner := strings.TrimSuffix(name, "Field")
+ section := ""
+ switch owner {
+ case "Border":
+ section = "border"
+ case "Fill":
+ section = "fill"
+ case "Alignment":
+ section = "align"
+ }
+ return enumDocumentation{"identifies a public field of excelize." + owner + "; these values are field names rather than formatting values", section}
+ }
+ return enumDocumentation{"represents an Excelize style selector", ""}
+}
+
+func docLink(_ enumDocumentation) string {
+ return officialStyleDocs
+}
+
+// documentEnums adds GoDoc to generated enum types and every named constant.
+// Descriptions are produced at generation time, so regeneration preserves them.
+func documentEnums(source []byte) ([]byte, error) {
+ set := token.NewFileSet()
+ file, err := parser.ParseFile(set, "generated.go", source, parser.ParseComments)
+ if err != nil {
+ return nil, err
+ }
+ formatCodes := map[string]string{}
+ for _, declaration := range file.Decls {
+ function, ok := declaration.(*ast.FuncDecl)
+ if !ok || function.Name.Name != "Code" {
+ continue
+ }
+ ast.Inspect(function.Body, func(node ast.Node) bool {
+ clause, ok := node.(*ast.CaseClause)
+ if !ok || len(clause.List) != 1 || len(clause.Body) != 1 {
+ return true
+ }
+ name, ok := clause.List[0].(*ast.Ident)
+ if !ok {
+ return true
+ }
+ statement, ok := clause.Body[0].(*ast.ReturnStmt)
+ if !ok || len(statement.Results) < 1 {
+ return true
+ }
+ value, err := stringLiteral(statement.Results[0])
+ if err == nil {
+ formatCodes[name.Name] = value
+ }
+ return true
+ })
+ }
+ typeNames := map[string]bool{}
+ type insertion struct {
+ offset int
+ text string
+ }
+ var edits []insertion
+ add := func(pos token.Pos, name, description string, doc enumDocumentation) {
+ edits = append(edits, insertion{set.Position(pos).Offset, fmt.Sprintf("// %s %s.\n//\n// See %s\n", name, description, docLink(doc))})
+ }
+ for _, decl := range file.Decls {
+ group, ok := decl.(*ast.GenDecl)
+ if !ok || group.Tok != token.TYPE {
+ continue
+ }
+ for _, raw := range group.Specs {
+ spec := raw.(*ast.TypeSpec)
+ underlying, ok := spec.Type.(*ast.Ident)
+ if !ok {
+ continue
+ }
+ if underlying.Name != "int" && underlying.Name != "uint64" && underlying.Name != "string" {
+ continue
+ }
+ name := spec.Name.Name
+ typeNames[name] = true
+ doc := enumDoc(name)
+ if spec.Doc == nil && group.Doc == nil {
+ add(group.Pos(), name, doc.description, doc)
+ }
+ }
+ }
+ for _, decl := range file.Decls {
+ group, ok := decl.(*ast.GenDecl)
+ if !ok || group.Tok != token.CONST {
+ continue
+ }
+ currentType := ""
+ for _, raw := range group.Specs {
+ spec := raw.(*ast.ValueSpec)
+ if id, ok := spec.Type.(*ast.Ident); ok {
+ currentType = id.Name
+ }
+ if !typeNames[currentType] {
+ continue
+ }
+ for _, id := range spec.Names {
+ if spec.Doc != nil {
+ continue
+ }
+ name := id.Name
+ doc := enumDoc(currentType)
+ description := enumValueDescription(currentType, strings.TrimPrefix(name, currentType))
+ switch {
+ case strings.HasSuffix(name, "Count"):
+ description = "is the number of generated choices; it is not a valid formatting value"
+ case strings.HasSuffix(currentType, "Field"):
+ description = "identifies excelize." + strings.TrimSuffix(currentType, "Field") + "." + strings.TrimPrefix(name, currentType)
+ case strings.HasPrefix(name, "NumberFormatID"):
+ description = "selects Excelize number-format ID " + strings.TrimPrefix(name, "NumberFormatID")
+ if code, ok := formatCodes[name]; ok {
+ description += " with format code " + strconv.Quote(code)
+ } else {
+ description += "; its format depends on the language selected through CodeForLanguage"
+ }
+ case strings.HasPrefix(name, "GradientShadingPreset"):
+ description = "selects gradient preset " + strings.TrimPrefix(name, "GradientShadingPreset") + " in the selected Excelize dependency"
+ case name == "IndexedColorUnset":
+ description = "leaves the indexed font color selector unspecified (ID -1)"
+ case strings.HasPrefix(name, "IndexedColorIndex"):
+ description = "selects palette index " + strings.TrimPrefix(name, "IndexedColorIndex") + "; the workbook palette determines its RGB color"
+ case name == "IndexedColorSystemForeground":
+ description = "selects the system foreground color (index 64)"
+ case name == "IndexedColorSystemBackground":
+ description = "selects the system background color (index 65)"
+ case name == "AlignmentReadingOrderContext":
+ description = "derives text direction from the first strong directional character"
+ case name == "AlignmentReadingOrderLeftToRight":
+ description = "reads cell text from left to right"
+ case name == "AlignmentReadingOrderRightToLeft":
+ description = "reads cell text from right to left"
+ case len(spec.Values) == 1:
+ if literal, ok := spec.Values[0].(*ast.BasicLit); ok {
+ if literal.Kind == token.STRING {
+ value, e := strconv.Unquote(literal.Value)
+ if e != nil {
+ return nil, e
+ }
+ if value == "" {
+ description = "leaves the formatting selector unset"
+ } else {
+ description = stringValueDescription(currentType, value)
+ }
+ } else {
+ description += " (ID " + literal.Value + ")"
+ }
+ }
+ }
+ add(spec.Pos(), name, description, doc)
+ }
+ }
+ }
+ sort.SliceStable(edits, func(i, j int) bool { return edits[i].offset > edits[j].offset })
+ result := string(source)
+ for _, edit := range edits {
+ result = result[:edit.offset] + edit.text + result[edit.offset:]
+ }
+ return []byte(result), nil
+}
+
+func enumValueDescription(kind, value string) string {
+ if kind == "BorderStyle" {
+ names := map[string]string{"None": "no border", "Thin": "a thin solid border", "Medium": "a medium solid border", "Dashed": "a dashed border", "Dotted": "a dotted border", "Thick": "a thick solid border", "Double": "a double-line border", "Hair": "a hairline border", "MediumDashed": "a medium dashed border", "DashDot": "a dash-dot border", "MediumDashDot": "a medium dash-dot border", "DashDotDot": "a dash-dot-dot border", "MediumDashDotDot": "a medium dash-dot-dot border", "SlantDashDot": "a slanted dash-dot border"}
+ if description, ok := names[value]; ok {
+ return "selects " + description
+ }
+ }
+ if kind == "FillPattern" {
+ return "selects the " + strconv.Quote(strings.ToLower(value[:1])+value[1:]) + " cell-fill pattern"
+ }
+ if kind == "ThemeColor" {
+ return "selects the workbook theme's " + value + " color slot"
+ }
+ if kind == "FontCharset" {
+ return "selects the " + value + " font character set"
+ }
+ return "selects " + value
+}
+
+func stringValueDescription(kind, value string) string {
+ meanings := map[string]map[string]string{
+ "BorderPosition": {"left": "selects the left cell edge", "right": "selects the right cell edge", "top": "selects the top cell edge", "bottom": "selects the bottom cell edge", "diagonalUp": "selects the diagonal from bottom-left to top-right", "diagonalDown": "selects the diagonal from top-left to bottom-right"},
+ "FillType": {"pattern": "uses the selected fill pattern and its foreground color", "gradient": "uses the selected gradient preset with two endpoint colors"},
+ "AlignmentHorizontal": {"general": "aligns according to the cell value's data type", "left": "aligns text to the left edge", "center": "centers text horizontally", "right": "aligns text to the right edge", "fill": "repeats the cell text across the available width", "justify": "justifies text to both horizontal edges", "centerContinuous": "centers text across adjacent cells", "distributed": "distributes text evenly across the available width"},
+ "AlignmentVertical": {"top": "aligns text to the top edge", "center": "centers text vertically", "bottom": "aligns text to the bottom edge", "justify": "justifies text vertically", "distributed": "distributes text evenly across the available height"},
+ "FontUnderline": {"none": "explicitly disables underlining", "single": "uses a single underline", "double": "uses a double underline"},
+ "FontVerticalAlign": {"baseline": "uses normal baseline text", "superscript": "raises text above the baseline", "subscript": "lowers text below the baseline"},
+ }
+ if text, ok := meanings[kind][value]; ok {
+ return text
+ }
+ if kind == "StyleLanguage" {
+ return "identifies language tag " + strconv.Quote(value) + " for localized number-format lookup"
+ }
+ return "selects " + strconv.Quote(value) + " for " + kind
+}
diff --git a/excelizeutil/cmd/gen-style-enums/godoc_test.go b/excelizeutil/cmd/gen-style-enums/godoc_test.go
new file mode 100644
index 0000000..cd51a10
--- /dev/null
+++ b/excelizeutil/cmd/gen-style-enums/godoc_test.go
@@ -0,0 +1,90 @@
+package main
+
+import (
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "strings"
+ "testing"
+)
+
+func TestEnumDocumentationCoversTypesAndConstants(t *testing.T) {
+ dir, err := excelizeModuleDir()
+ if err != nil {
+ t.Fatal(err)
+ }
+ public, _, err := generatedSources(dir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ file, err := parser.ParseFile(token.NewFileSet(), "generated.go", public, parser.ParseComments)
+ if err != nil {
+ t.Fatal(err)
+ }
+ enums := map[string]bool{}
+ check := func(name string, doc *ast.CommentGroup) {
+ t.Helper()
+ if doc == nil {
+ t.Errorf("%s has no GoDoc", name)
+ return
+ }
+ text := doc.Text()
+ if !strings.HasPrefix(text, name+" ") {
+ t.Errorf("%s GoDoc must start with its name: %s", name, text)
+ }
+ if !strings.Contains(text, officialStyleDocs) {
+ t.Errorf("%s has no official documentation reference", name)
+ }
+ }
+ for _, decl := range file.Decls {
+ group, ok := decl.(*ast.GenDecl)
+ if !ok || group.Tok != token.TYPE {
+ continue
+ }
+ for _, raw := range group.Specs {
+ spec := raw.(*ast.TypeSpec)
+ underlying, ok := spec.Type.(*ast.Ident)
+ if !ok {
+ continue
+ }
+ if underlying.Name != "int" && underlying.Name != "string" && underlying.Name != "uint64" {
+ continue
+ }
+ enums[spec.Name.Name] = true
+ doc := spec.Doc
+ if doc == nil {
+ doc = group.Doc
+ }
+ check(spec.Name.Name, doc)
+ }
+ }
+ count := 0
+ for _, decl := range file.Decls {
+ group, ok := decl.(*ast.GenDecl)
+ if !ok || group.Tok != token.CONST {
+ continue
+ }
+ kind := ""
+ for _, raw := range group.Specs {
+ spec := raw.(*ast.ValueSpec)
+ if id, ok := spec.Type.(*ast.Ident); ok {
+ kind = id.Name
+ }
+ if !enums[kind] {
+ continue
+ }
+ for _, name := range spec.Names {
+ check(name.Name, spec.Doc)
+ count++
+ }
+ }
+ }
+ if len(enums) < 10 || count < 100 {
+ t.Fatal("enum documentation inventory is unexpectedly small")
+ }
+ for _, fragment := range []string{"selects a thin solid border", "with format code", "path bounds", "identifies excelize.Font.Bold"} {
+ if !strings.Contains(string(public), fragment) {
+ t.Errorf("missing meaningful explanation %q", fragment)
+ }
+ }
+}
diff --git a/excelizeutil/cmd/gen-style-enums/main.go b/excelizeutil/cmd/gen-style-enums/main.go
new file mode 100644
index 0000000..2d6c88c
--- /dev/null
+++ b/excelizeutil/cmd/gen-style-enums/main.go
@@ -0,0 +1,294 @@
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/format"
+ "go/parser"
+ "go/token"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "unicode"
+)
+
+type enumSpec struct {
+ typeName string
+ constantPrefix string
+ packageVar string
+ legacyFunction string
+ legacyVariable string
+}
+
+var sourceDir = flag.String("source", "", "Excelize source directory (default: selected module)")
+var checkOutput = flag.Bool("check", false, "fail if generated files need updating")
+
+func main() {
+ flag.Parse()
+ if err := generate(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func generate() error {
+ moduleDir := *sourceDir
+ var err error
+ if moduleDir == "" {
+ moduleDir, err = excelizeModuleDir()
+ }
+ if err != nil {
+ return err
+ }
+ public, private, err := generatedSources(moduleDir)
+ if err != nil {
+ return err
+ }
+ if err := saveGenerated("../excelizestyle/style_enums_gen.go", public); err != nil {
+ return err
+ }
+ return saveGenerated("style_enums_gen.go", private)
+}
+
+func generatedSources(moduleDir string) ([]byte, []byte, error) {
+ filename := filepath.Join(moduleDir, "styles.go")
+ file, err := parser.ParseFile(token.NewFileSet(), filename, nil, parser.AllErrors|parser.ParseComments)
+ if err != nil {
+ return nil, nil, fmt.Errorf("parse Excelize styles.go: %w", err)
+ }
+
+ specs := []enumSpec{
+ {
+ typeName: "fillPattern",
+ constantPrefix: "fillPattern",
+ packageVar: "styleFillPatterns",
+ legacyFunction: "newFills",
+ legacyVariable: "patterns",
+ },
+ {
+ typeName: "borderStyle",
+ constantPrefix: "borderStyle",
+ packageVar: "styleBorders",
+ legacyFunction: "newBorders",
+ legacyVariable: "styles",
+ },
+ }
+
+ var output bytes.Buffer
+ output.WriteString("// Code generated by go generate; DO NOT EDIT.\n\npackage excelizeutil\n\nimport \"github.com/tomtwinkle/excelizeam/excelizestyle\"\n\n")
+ for _, spec := range specs {
+ publicName, err := enumIdentifier(spec.typeName)
+ if err != nil {
+ return nil, nil, err
+ }
+ fmt.Fprintf(&output, "type %s = excelizestyle.%s\nconst %sNone = excelizestyle.%sNone\nfunc parse%s(value string) (%s,bool) { return excelizestyle.Parse%s(value) }\n\n", spec.typeName, publicName, spec.typeName, publicName, publicName, spec.typeName, publicName)
+ }
+
+ public, geometry, err := additionalEnums(moduleDir, file, specs)
+ if err != nil {
+ return nil, nil, err
+ }
+ output.Write(geometry)
+ public, err = format.Source(public)
+ if err != nil {
+ return nil, nil, err
+ }
+ public, err = documentEnums(public)
+ if err != nil {
+ return nil, nil, err
+ }
+ public, err = format.Source(public)
+ if err != nil {
+ return nil, nil, fmt.Errorf("format public enums: %w", err)
+ }
+ formatted, err := format.Source(output.Bytes())
+ if err != nil {
+ return nil, nil, fmt.Errorf("format generated enums: %w", err)
+ }
+ return public, formatted, nil
+}
+
+func excelizeModuleDir() (string, error) {
+ const modulePath = "github.com/xuri/excelize/v2"
+ download := exec.Command("go", "mod", "download", modulePath)
+ if output, err := download.CombinedOutput(); err != nil {
+ return "", fmt.Errorf("download Excelize module: %w: %s", err, strings.TrimSpace(string(output)))
+ }
+ command := exec.Command("go", "list", "-m", "-f", "{{.Dir}}", modulePath)
+ output, err := command.CombinedOutput()
+ if err != nil {
+ return "", fmt.Errorf("locate Excelize module: %w: %s", err, strings.TrimSpace(string(output)))
+ }
+ dir := strings.TrimSpace(string(output))
+ if dir == "" {
+ return "", fmt.Errorf("locate Excelize module: go list returned an empty directory")
+ }
+ return dir, nil
+}
+
+func findEnumValues(file *ast.File, spec enumSpec) ([]string, error) {
+ for _, declaration := range file.Decls {
+ group, ok := declaration.(*ast.GenDecl)
+ if !ok || group.Tok != token.VAR {
+ continue
+ }
+ for _, rawSpec := range group.Specs {
+ valueSpec, ok := rawSpec.(*ast.ValueSpec)
+ if !ok {
+ continue
+ }
+ for i, name := range valueSpec.Names {
+ if name.Name != spec.packageVar {
+ continue
+ }
+ if i >= len(valueSpec.Values) {
+ return nil, fmt.Errorf("Excelize styles.go: %s has no initializer", spec.packageVar)
+ }
+ return stringValues(valueSpec.Values[i], spec.packageVar)
+ }
+ }
+ }
+
+ for _, declaration := range file.Decls {
+ function, ok := declaration.(*ast.FuncDecl)
+ if !ok || function.Name.Name != spec.legacyFunction || function.Body == nil {
+ continue
+ }
+ var values []string
+ var found bool
+ var foundErr error
+ ast.Inspect(function.Body, func(node ast.Node) bool {
+ assignment, ok := node.(*ast.AssignStmt)
+ if !ok {
+ return true
+ }
+ for i, left := range assignment.Lhs {
+ name, ok := left.(*ast.Ident)
+ if !ok || name.Name != spec.legacyVariable || i >= len(assignment.Rhs) {
+ continue
+ }
+ values, foundErr = stringValues(assignment.Rhs[i], spec.legacyVariable)
+ found = foundErr == nil
+ return false
+ }
+ return true
+ })
+ if foundErr != nil {
+ return nil, foundErr
+ }
+ if found {
+ return values, nil
+ }
+ break
+ }
+
+ return nil, fmt.Errorf(
+ "Excelize styles.go: could not find %s (expected package variable %s or %s.%s)",
+ spec.typeName, spec.packageVar, spec.legacyFunction, spec.legacyVariable,
+ )
+}
+
+func stringValues(expression ast.Expr, label string) ([]string, error) {
+ literal, ok := expression.(*ast.CompositeLit)
+ if !ok {
+ return nil, fmt.Errorf("Excelize styles.go: %s is not a composite literal", label)
+ }
+ array, ok := literal.Type.(*ast.ArrayType)
+ if !ok {
+ return nil, fmt.Errorf("Excelize styles.go: %s is not a slice or array", label)
+ }
+ identifier, ok := array.Elt.(*ast.Ident)
+ if !ok || identifier.Name != "string" {
+ return nil, fmt.Errorf("Excelize styles.go: %s is not a string slice", label)
+ }
+ values := make([]string, 0, len(literal.Elts))
+ for _, element := range literal.Elts {
+ basic, ok := element.(*ast.BasicLit)
+ if !ok || basic.Kind != token.STRING {
+ return nil, fmt.Errorf("Excelize styles.go: %s contains a non-string value", label)
+ }
+ value, err := strconv.Unquote(basic.Value)
+ if err != nil {
+ return nil, fmt.Errorf("Excelize styles.go: decode %s value: %w", label, err)
+ }
+ values = append(values, value)
+ }
+ if len(values) == 0 {
+ return nil, fmt.Errorf("Excelize styles.go: %s is empty", label)
+ }
+ return values, nil
+}
+
+func writeEnum(output *bytes.Buffer, spec enumSpec, values []string) error {
+ identifiers := make([]string, len(values))
+ seenValues := make(map[string]struct{}, len(values))
+ seenIdentifiers := make(map[string]struct{}, len(values))
+ for i, value := range values {
+ if _, exists := seenValues[value]; exists {
+ return fmt.Errorf("Excelize styles.go: %s contains duplicate value %q", spec.typeName, value)
+ }
+ seenValues[value] = struct{}{}
+ name, err := enumIdentifier(value)
+ if err != nil {
+ return fmt.Errorf("Excelize styles.go: invalid %s value %q: %w", spec.typeName, value, err)
+ }
+ if _, exists := seenIdentifiers[name]; exists {
+ return fmt.Errorf("Excelize styles.go: %s values produce duplicate enum %s", spec.typeName, name)
+ }
+ seenIdentifiers[name] = struct{}{}
+ identifiers[i] = name
+ }
+
+ fmt.Fprintf(output, "type %s int\n\nconst (\n", spec.typeName)
+ for i, identifier := range identifiers {
+ if i == 0 {
+ fmt.Fprintf(output, "\t%s%s %s = iota\n", spec.constantPrefix, identifier, spec.typeName)
+ } else {
+ fmt.Fprintf(output, "\t%s%s\n", spec.constantPrefix, identifier)
+ }
+ }
+ fmt.Fprintf(output, "\t%sCount\n)\n\n", spec.typeName)
+
+ fmt.Fprintf(output, "func (value %s) String() string {\n\tswitch value {\n", spec.typeName)
+ for i, identifier := range identifiers {
+ fmt.Fprintf(output, "\tcase %s%s:\n\t\treturn %s\n", spec.constantPrefix, identifier, strconv.Quote(values[i]))
+ }
+ fmt.Fprintf(output, "\tdefault:\n\t\treturn \"\"\n\t}\n}\n\n")
+
+ typeName, err := enumIdentifier(spec.typeName)
+ if err != nil {
+ return err
+ }
+ parsePrefix := "parse"
+ if unicode.IsUpper([]rune(spec.typeName)[0]) {
+ parsePrefix = "Parse"
+ }
+ fmt.Fprintf(output, "func %s%s(value string) (%s, bool) {\n\tswitch value {\n", parsePrefix, typeName, spec.typeName)
+ for i, identifier := range identifiers {
+ fmt.Fprintf(output, "\tcase %s:\n\t\treturn %s%s, true\n", strconv.Quote(values[i]), spec.constantPrefix, identifier)
+ }
+ fmt.Fprintf(output, "\tdefault:\n\t\treturn 0, false\n\t}\n}\n\n")
+ return nil
+}
+
+func enumIdentifier(value string) (string, error) {
+ runes := []rune(value)
+ if len(runes) == 0 {
+ return "", fmt.Errorf("empty value")
+ }
+ for _, character := range runes {
+ if !unicode.IsLetter(character) && !unicode.IsDigit(character) && character != '_' {
+ return "", fmt.Errorf("unsupported character %q", character)
+ }
+ }
+ if !unicode.IsLetter(runes[0]) && runes[0] != '_' {
+ return "", fmt.Errorf("identifier must start with a letter or underscore")
+ }
+ runes[0] = unicode.ToUpper(runes[0])
+ name := string(runes)
+ return name, nil
+}
diff --git a/excelizeutil/excelizeutil.go b/excelizeutil/excelizeutil.go
new file mode 100644
index 0000000..39a120f
--- /dev/null
+++ b/excelizeutil/excelizeutil.go
@@ -0,0 +1,891 @@
+//go:generate go run ./cmd/gen-style-enums
+
+package excelizeutil
+
+import (
+ "archive/zip"
+ "bytes"
+ "encoding/xml"
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+
+ "github.com/tomtwinkle/excelizeam/excelizestyle"
+ "github.com/xuri/excelize/v2"
+)
+
+var errInvalidStyleReference = errors.New("invalid style reference")
+
+// GetStyle returns the effective style for a cell in an XLSX workbook.
+// It returns an error when the workbook, coordinates, sheet, or cell style is invalid.
+func GetStyle(excelBuffer bytes.Buffer, sheetName string, corIdx, rowIdx int) (excelize.Style, error) {
+ themeColors, numberFormats, indexedColors := readStyleMetadata(excelBuffer)
+ f, err := excelize.OpenReader(&excelBuffer)
+ if err != nil {
+ return excelize.Style{}, fmt.Errorf("open workbook: %w", err)
+ }
+ defer func() { _ = f.Close() }()
+
+ cell, err := excelize.CoordinatesToCellName(corIdx, rowIdx)
+ if err != nil {
+ return excelize.Style{}, fmt.Errorf("convert cell coordinates: %w", err)
+ }
+ styleID, err := f.GetCellStyle(sheetName, cell)
+ if err != nil {
+ return excelize.Style{}, fmt.Errorf("get cell style: %w", err)
+ }
+
+ format, err := resolveCellFormat(f, styleID)
+ if err != nil {
+ return excelize.Style{}, fmt.Errorf("resolve cell style: %w", err)
+ }
+ if err := validateCellStyleReferences(f, format, numberFormats); err != nil {
+ return excelize.Style{}, fmt.Errorf("resolve cell style: %w", err)
+ }
+ numFmt, customNumFmt := getCellNumberFormat(format.NumFmtID, numberFormats)
+ style := excelize.Style{
+ Border: getCellBorder(f, format.BorderID, themeColors, indexedColors),
+ Fill: getCellFill(f, format.FillID, themeColors, indexedColors),
+ Font: getCellFont(f, format.FontID, format.HasFont, themeColors, indexedColors),
+ Alignment: format.Alignment,
+ Protection: format.Protection,
+ NumFmt: numFmt,
+ CustomNumFmt: customNumFmt,
+ }
+ applyNativeNumberFormatMetadata(&style, f, styleID, format, customNumFmt)
+ return style, nil
+}
+
+// GetStyleDefinition returns the effective cell style with typed categorical fields.
+func GetStyleDefinition(excelBuffer bytes.Buffer, sheetName string, column, row int) (excelizestyle.StyleDefinition, error) {
+ style, err := GetStyle(excelBuffer, sheetName, column, row)
+ if err != nil {
+ return excelizestyle.StyleDefinition{}, err
+ }
+ return excelizestyle.StyleDefinitionFromExcelize(style), nil
+}
+
+type resolvedCellFormat struct {
+ FontID int
+ HasFont bool
+ FillID int
+ BorderID int
+ NumFmtID int
+ Alignment *excelize.Alignment
+ Protection *excelize.Protection
+}
+
+func resolveCellFormat(f *excelize.File, styleID int) (resolvedCellFormat, error) {
+ if f.Styles == nil || f.Styles.CellXfs == nil || styleID < 0 || styleID >= len(f.Styles.CellXfs.Xf) {
+ return resolvedCellFormat{}, fmt.Errorf("%w: cell style ID %d is out of range", errInvalidStyleReference, styleID)
+ }
+ cellXF := f.Styles.CellXfs.Xf[styleID]
+ resolved := resolvedCellFormat{
+ FontID: integerValue(cellXF.FontID),
+ HasFont: inheritedStylePresent(cellXF.FontID, nil, cellXF.ApplyFont),
+ FillID: integerValue(cellXF.FillID),
+ BorderID: integerValue(cellXF.BorderID),
+ NumFmtID: integerValue(cellXF.NumFmtID),
+ }
+ alignment := cellXF.Alignment
+ protection := cellXF.Protection
+ if cellXF.XfID != nil {
+ if f.Styles.CellStyleXfs == nil || *cellXF.XfID < 0 || *cellXF.XfID >= len(f.Styles.CellStyleXfs.Xf) {
+ return resolvedCellFormat{}, fmt.Errorf("%w: xfId=%d references cellStyleXfs with %d entries", errInvalidStyleReference, *cellXF.XfID, cellStyleXFCount(f))
+ }
+ baseXF := f.Styles.CellStyleXfs.Xf[*cellXF.XfID]
+ resolved.FontID = inheritedStyleID(cellXF.FontID, baseXF.FontID, cellXF.ApplyFont)
+ resolved.HasFont = inheritedStylePresent(cellXF.FontID, baseXF.FontID, cellXF.ApplyFont)
+ resolved.FillID = inheritedStyleID(cellXF.FillID, baseXF.FillID, cellXF.ApplyFill)
+ resolved.BorderID = inheritedStyleID(cellXF.BorderID, baseXF.BorderID, cellXF.ApplyBorder)
+ resolved.NumFmtID = inheritedStyleID(cellXF.NumFmtID, baseXF.NumFmtID, cellXF.ApplyNumberFormat)
+
+ if cellXF.ApplyAlignment == nil || !*cellXF.ApplyAlignment {
+ if baseXF.Alignment != nil {
+ alignment = baseXF.Alignment
+ } else if cellXF.ApplyAlignment != nil {
+ alignment = nil
+ }
+ }
+ if cellXF.ApplyProtection == nil || !*cellXF.ApplyProtection {
+ if baseXF.Protection != nil {
+ protection = baseXF.Protection
+ } else if cellXF.ApplyProtection != nil {
+ protection = nil
+ }
+ }
+ }
+ if alignment != nil {
+ resolved.Alignment = &excelize.Alignment{
+ Horizontal: alignment.Horizontal,
+ Indent: alignment.Indent,
+ JustifyLastLine: alignment.JustifyLastLine,
+ ReadingOrder: alignment.ReadingOrder,
+ RelativeIndent: alignment.RelativeIndent,
+ ShrinkToFit: alignment.ShrinkToFit,
+ TextRotation: alignment.TextRotation,
+ Vertical: alignment.Vertical,
+ WrapText: alignment.WrapText,
+ }
+ }
+ if protection != nil {
+ resolved.Protection = &excelize.Protection{Locked: true}
+ if protection.Locked != nil {
+ resolved.Protection.Locked = *protection.Locked
+ }
+ if protection.Hidden != nil {
+ resolved.Protection.Hidden = *protection.Hidden
+ }
+ }
+ return resolved, nil
+}
+
+func cellStyleXFCount(f *excelize.File) int {
+ if f == nil || f.Styles == nil || f.Styles.CellStyleXfs == nil {
+ return 0
+ }
+ return len(f.Styles.CellStyleXfs.Xf)
+}
+
+func validateCellStyleReferences(f *excelize.File, format resolvedCellFormat, numberFormats map[int]string) error {
+ styles := f.Styles
+ if format.HasFont {
+ if err := validateStyleCollectionReference("fontId", format.FontID, fontCount(f)); err != nil {
+ return err
+ }
+ if styles.Fonts.Font[format.FontID] == nil {
+ return fmt.Errorf("%w: fontId=%d references an empty font entry", errInvalidStyleReference, format.FontID)
+ }
+ }
+ if err := validateStyleCollectionReference("fillId", format.FillID, fillCount(f)); err != nil {
+ return err
+ }
+ if styles.Fills.Fill[format.FillID] == nil {
+ return fmt.Errorf("%w: fillId=%d references an empty fill entry", errInvalidStyleReference, format.FillID)
+ }
+ if err := validateStyleCollectionReference("borderId", format.BorderID, borderCount(f)); err != nil {
+ return err
+ }
+ if styles.Borders.Border[format.BorderID] == nil {
+ return fmt.Errorf("%w: borderId=%d references an empty border entry", errInvalidStyleReference, format.BorderID)
+ }
+ if format.NumFmtID < 0 {
+ return fmt.Errorf("%w: numFmtId=%d is negative", errInvalidStyleReference, format.NumFmtID)
+ }
+ if format.NumFmtID >= 164 {
+ if _, ok := numberFormats[format.NumFmtID]; !ok {
+ return fmt.Errorf("%w: numFmtId=%d has no custom number format definition", errInvalidStyleReference, format.NumFmtID)
+ }
+ }
+ return nil
+}
+
+func validateStyleCollectionReference(name string, id, length int) error {
+ if id < 0 || id >= length {
+ return fmt.Errorf("%w: %s=%d is out of range for a collection with %d entries", errInvalidStyleReference, name, id, length)
+ }
+ return nil
+}
+
+func fontCount(f *excelize.File) int {
+ if f == nil || f.Styles == nil || f.Styles.Fonts == nil {
+ return 0
+ }
+ return len(f.Styles.Fonts.Font)
+}
+
+func fillCount(f *excelize.File) int {
+ if f == nil || f.Styles == nil || f.Styles.Fills == nil {
+ return 0
+ }
+ return len(f.Styles.Fills.Fill)
+}
+
+func borderCount(f *excelize.File) int {
+ if f == nil || f.Styles == nil || f.Styles.Borders == nil {
+ return 0
+ }
+ return len(f.Styles.Borders.Border)
+}
+
+func inheritedStylePresent(child, parent *int, apply *bool) bool {
+ if apply != nil && *apply {
+ // fontId defaults to zero in CT_Xf, so apply=true with no explicit
+ // fontId still applies the default (possibly customized) font record.
+ return true
+ }
+ if parent != nil {
+ return true
+ }
+ if apply != nil { // apply=false with no base XF means no child style is active.
+ return false
+ }
+ return child != nil && *child != 0
+}
+
+func integerValue(value *int) int {
+ if value == nil {
+ return 0
+ }
+ return *value
+}
+
+func inheritedStyleID(child, parent *int, apply *bool) int {
+ if apply != nil && *apply {
+ return integerValue(child)
+ }
+ if parent != nil {
+ return *parent
+ }
+ if apply != nil && !*apply {
+ return 0
+ }
+ return integerValue(child)
+}
+
+func getCellBorder(f *excelize.File, borderID int, themeColors []string, indexedColors map[int]string) []excelize.Border {
+ if f.Styles.Borders == nil || borderID < 0 || borderID >= len(f.Styles.Borders.Border) || f.Styles.Borders.Border[borderID] == nil {
+ return nil
+ }
+
+ definition := f.Styles.Borders.Border[borderID]
+ borders := make([]excelize.Border, 0, 6)
+ appendBorder := func(side, style string, color *xlsxColor) {
+ if style == "" {
+ return
+ }
+ border := excelize.Border{
+ Type: side,
+ Style: borderStyleID(style),
+ }
+ if colors := getCellFillColor(color, themeColors, indexedColors); len(colors) > 0 {
+ border.Color = colors[0]
+ }
+ borders = append(borders, border)
+ }
+
+ topStyle, topColor := borderLine(definition.Top)
+ bottomStyle, bottomColor := borderLine(definition.Bottom)
+ leftStyle, leftColor := borderLine(definition.Left)
+ rightStyle, rightColor := borderLine(definition.Right)
+ appendBorder("top", topStyle, topColor)
+ appendBorder("bottom", bottomStyle, bottomColor)
+ appendBorder("left", leftStyle, leftColor)
+ appendBorder("right", rightStyle, rightColor)
+ if definition.DiagonalUp {
+ diagonalStyle, diagonalColor := borderLine(definition.Diagonal)
+ appendBorder("diagonalUp", diagonalStyle, diagonalColor)
+ }
+ if definition.DiagonalDown {
+ diagonalStyle, diagonalColor := borderLine(definition.Diagonal)
+ appendBorder("diagonalDown", diagonalStyle, diagonalColor)
+ }
+ return borders
+}
+
+func borderLine(line any) (string, *xlsxColor) {
+ value := reflect.ValueOf(line)
+ if !value.IsValid() {
+ return "", nil
+ }
+ if value.Kind() == reflect.Ptr {
+ if value.IsNil() {
+ return "", nil
+ }
+ value = value.Elem()
+ }
+ if value.Kind() != reflect.Struct {
+ return "", nil
+ }
+ style := value.FieldByName("Style")
+ if !style.IsValid() || style.Kind() != reflect.String {
+ return "", nil
+ }
+ return style.String(), colorValue(value.FieldByName("Color"))
+}
+
+func borderStyleID(style string) int {
+ if value, ok := parseBorderStyle(style); ok {
+ return int(value)
+ }
+ return int(borderStyleNone)
+}
+
+func getCellFill(f *excelize.File, fillID int, themeColors []string, indexedColors map[int]string) excelize.Fill {
+ if f.Styles.Fills == nil || fillID < 0 || fillID >= len(f.Styles.Fills.Fill) || f.Styles.Fills.Fill[fillID] == nil {
+ return excelize.Fill{}
+ }
+ definition := f.Styles.Fills.Fill[fillID]
+ if definition.GradientFill != nil {
+ return getCellGradientFill(definition.GradientFill, themeColors, indexedColors)
+ }
+ if definition.PatternFill == nil {
+ return excelize.Fill{}
+ }
+ patternFill := definition.PatternFill
+
+ pattern := int(fillPatternNone)
+ if value, ok := parseFillPattern(patternFill.PatternType); ok {
+ pattern = int(value)
+ }
+
+ color := patternFill.FgColor
+ if color == nil {
+ color = patternFill.BgColor
+ }
+ return excelize.Fill{
+ Type: "pattern",
+ Pattern: pattern,
+ Color: getCellFillColor((*xlsxColor)(color), themeColors, indexedColors),
+ }
+}
+
+type gradientGeometry struct {
+ typeName string
+ degree float64
+ left float64
+ right float64
+ top float64
+ bottom float64
+ positions []float64
+}
+
+func getCellGradientFill(value any, themeColors []string, indexedColors map[int]string) excelize.Fill {
+ geometry, colors, ok := readGradient(value)
+ if !ok {
+ return excelize.Fill{Type: "gradient"}
+ }
+ for shading, preset := range gradientGeometries() {
+ if !sameGradientGeometry(geometry, preset) || len(colors) != len(preset.positions) {
+ continue
+ }
+ matchesPositions := true
+ for index, position := range preset.positions {
+ if colors[index].position != position {
+ matchesPositions = false
+ break
+ }
+ }
+ if !matchesPositions {
+ continue
+ }
+ resolved := make([][]string, len(colors))
+ for index, stop := range colors {
+ resolved[index] = getCellFillColor(stop.color, themeColors, indexedColors)
+ if len(resolved[index]) == 0 {
+ return excelize.Fill{Type: "gradient"}
+ }
+ }
+ if len(colors) == 3 && !reflect.DeepEqual(resolved[0], resolved[2]) {
+ // Excelize's public API models these presets as color0, color1,
+ // color0. A different final stop cannot be represented.
+ return excelize.Fill{Type: "gradient"}
+ }
+ return excelize.Fill{Type: "gradient", Shading: shading, Color: []string{resolved[0][0], resolved[1][0]}}
+ }
+ return excelize.Fill{Type: "gradient"}
+}
+
+func readGradient(value any) (gradientGeometry, []struct {
+ position float64
+ color *xlsxColor
+}, bool) {
+ ref := reflect.ValueOf(value)
+ if !ref.IsValid() {
+ return gradientGeometry{}, nil, false
+ }
+ if ref.Kind() == reflect.Ptr {
+ if ref.IsNil() {
+ return gradientGeometry{}, nil, false
+ }
+ ref = ref.Elem()
+ }
+ if ref.Kind() != reflect.Struct {
+ return gradientGeometry{}, nil, false
+ }
+ getFloat := func(name string) float64 {
+ field := ref.FieldByName(name)
+ if field.IsValid() && field.CanFloat() {
+ return field.Float()
+ }
+ return 0
+ }
+ getString := func(name string) string {
+ field := ref.FieldByName(name)
+ if field.IsValid() && field.Kind() == reflect.String {
+ return field.String()
+ }
+ return ""
+ }
+ geometry := gradientGeometry{
+ typeName: getString("Type"),
+ degree: getFloat("Degree"),
+ left: getFloat("Left"),
+ right: getFloat("Right"),
+ top: getFloat("Top"),
+ bottom: getFloat("Bottom"),
+ }
+ stops := ref.FieldByName("Stop")
+ if !stops.IsValid() || stops.Kind() != reflect.Slice {
+ return gradientGeometry{}, nil, false
+ }
+ colors := make([]struct {
+ position float64
+ color *xlsxColor
+ }, 0, stops.Len())
+ for index := 0; index < stops.Len(); index++ {
+ stop := stops.Index(index)
+ if stop.Kind() == reflect.Ptr {
+ if stop.IsNil() {
+ return gradientGeometry{}, nil, false
+ }
+ stop = stop.Elem()
+ }
+ position := stop.FieldByName("Position")
+ color := stop.FieldByName("Color")
+ if !position.IsValid() || !position.CanFloat() || !color.IsValid() {
+ return gradientGeometry{}, nil, false
+ }
+ colors = append(colors, struct {
+ position float64
+ color *xlsxColor
+ }{position: position.Float(), color: colorValue(color)})
+ }
+ geometry.positions = make([]float64, len(colors))
+ for index, stop := range colors {
+ geometry.positions[index] = stop.position
+ }
+ return geometry, colors, true
+}
+
+func hasExcelizeField(typ reflect.Type, fieldName string) bool {
+ _, ok := typ.FieldByName(fieldName)
+ return ok
+}
+
+func sameGradientGeometry(a, b gradientGeometry) bool {
+ return a.typeName == b.typeName && a.degree == b.degree && a.left == b.left && a.right == b.right && a.top == b.top && a.bottom == b.bottom
+}
+
+func getCellFont(f *excelize.File, fontID int, hasFont bool, themeColors []string, indexedColors map[int]string) *excelize.Font {
+ if f.Styles.Fonts == nil || fontID < 0 || fontID >= len(f.Styles.Fonts.Font) || (!hasFont && fontID == 0) || f.Styles.Fonts.Font[fontID] == nil {
+ return nil
+ }
+ font := f.Styles.Fonts.Font[fontID]
+ result := &excelize.Font{}
+ // Excelize v2.10.1 treats ColorIndexed's zero value as an explicit
+ // indexed color. Use -1 unless the OOXML color actually selects an index.
+ setExcelizeField(result, "ColorIndexed", -1)
+ result.Bold = xmlBooleanValue(font.B)
+ result.Italic = xmlBooleanValue(font.I)
+ if font.U != nil {
+ result.Underline = "single"
+ if font.U.Val != nil && *font.U.Val != "" {
+ result.Underline = *font.U.Val
+ }
+ }
+ if font.Name != nil && font.Name.Val != nil {
+ result.Family = *font.Name.Val
+ }
+ if font.Sz != nil && font.Sz.Val != nil {
+ result.Size = *font.Sz.Val
+ }
+ result.Strike = xmlBooleanValue(font.Strike)
+ color := colorValue(reflect.ValueOf(font.Color))
+ if color != nil {
+ if hasExcelizeField(reflect.TypeOf(excelize.Font{}), "ColorTint") {
+ // v2.10.1 exposes tint and the theme/indexed selectors separately.
+ // Keep the untinted RGB fallback; returning a resolved tint here too
+ // would cause NewStyle to serialize and apply the tint twice.
+ result.Color = normalizeRGB(color.RGB)
+ } else if colors := getCellFillColor(color, themeColors, indexedColors); len(colors) > 0 {
+ // Older Style APIs lack selector and tint fields, so keep appearance.
+ result.Color = colors[0]
+ }
+ }
+ if color != nil {
+ if color.RGB == "" && color.Theme == nil && !color.Auto {
+ setExcelizeField(result, "ColorIndexed", color.Indexed)
+ }
+ if color.Theme != nil {
+ setExcelizeField(result, "ColorTheme", color.Theme)
+ }
+ setExcelizeField(result, "ColorTint", color.Tint)
+ }
+ if charset, ok := xmlAttributeValue(font, "Charset", "Val"); ok {
+ setExcelizeField(result, "Charset", charset)
+ }
+ if vertical, ok := xmlAttributeValue(font, "VertAlign", "Val"); ok {
+ setExcelizeField(result, "VertAlign", vertical)
+ }
+ return result
+}
+
+func xmlBooleanValue(value any) bool {
+ ref := reflect.ValueOf(value)
+ if !ref.IsValid() || ref.Kind() != reflect.Ptr || ref.IsNil() {
+ return false
+ }
+ attribute := ref.Elem().FieldByName("Val")
+ if !attribute.IsValid() || (attribute.Kind() == reflect.Ptr && attribute.IsNil()) {
+ return true
+ }
+ if attribute.Kind() == reflect.Ptr {
+ attribute = attribute.Elem()
+ }
+ return attribute.Bool()
+}
+
+func xmlAttributeValue(value any, elementName, attributeName string) (any, bool) {
+ ref := reflect.ValueOf(value)
+ if !ref.IsValid() {
+ return nil, false
+ }
+ if ref.Kind() == reflect.Ptr {
+ if ref.IsNil() {
+ return nil, false
+ }
+ ref = ref.Elem()
+ }
+ element := ref.FieldByName(elementName)
+ if !element.IsValid() || element.Kind() != reflect.Ptr || element.IsNil() {
+ return nil, false
+ }
+ attribute := element.Elem().FieldByName(attributeName)
+ if !attribute.IsValid() {
+ return nil, false
+ }
+ if attribute.Kind() == reflect.Ptr {
+ if attribute.IsNil() {
+ return nil, false
+ }
+ attribute = attribute.Elem()
+ }
+ return attribute.Interface(), true
+}
+
+func colorValue(value reflect.Value) *xlsxColor {
+ if !value.IsValid() {
+ return nil
+ }
+ if value.Kind() == reflect.Ptr {
+ if value.IsNil() {
+ return nil
+ }
+ value = value.Elem()
+ }
+ if value.Kind() != reflect.Struct {
+ return nil
+ }
+ result := &xlsxColor{}
+ if field := value.FieldByName("Auto"); field.IsValid() && field.Kind() == reflect.Bool {
+ result.Auto = field.Bool()
+ }
+ if field := value.FieldByName("RGB"); field.IsValid() && field.Kind() == reflect.String {
+ result.RGB = field.String()
+ }
+ if field := value.FieldByName("Indexed"); field.IsValid() && field.Kind() == reflect.Int {
+ result.Indexed = int(field.Int())
+ }
+ if field := value.FieldByName("Theme"); field.IsValid() && field.Kind() == reflect.Ptr && !field.IsNil() {
+ theme := int(field.Elem().Int())
+ result.Theme = &theme
+ }
+ if field := value.FieldByName("Tint"); field.IsValid() && field.Kind() == reflect.Float64 {
+ result.Tint = field.Float()
+ }
+ return result
+}
+
+func setExcelizeField(target any, name string, value any) bool {
+ ref := reflect.ValueOf(target)
+ if !ref.IsValid() || ref.Kind() != reflect.Ptr || ref.IsNil() {
+ return false
+ }
+ field := ref.Elem().FieldByName(name)
+ if !field.IsValid() || !field.CanSet() {
+ return false
+ }
+ input := reflect.ValueOf(value)
+ if field.Kind() == reflect.Ptr && input.Type().AssignableTo(field.Type().Elem()) {
+ pointer := reflect.New(field.Type().Elem())
+ pointer.Elem().Set(input)
+ field.Set(pointer)
+ return true
+ }
+ if input.Type().AssignableTo(field.Type()) {
+ field.Set(input)
+ return true
+ }
+ if input.Type().ConvertibleTo(field.Type()) {
+ field.Set(input.Convert(field.Type()))
+ return true
+ }
+ return false
+}
+
+func getCellNumberFormat(numFmtID int, numberFormats map[int]string) (int, *string) {
+ if format, ok := numberFormats[numFmtID]; ok {
+ return 0, &format
+ }
+ if numFmtID >= 0 && numFmtID < 164 {
+ return numFmtID, nil
+ }
+ return 0, nil
+}
+
+type excelizeStyleGetter interface {
+ GetStyle(int) (*excelize.Style, error)
+}
+
+func applyNativeNumberFormatMetadata(style *excelize.Style, f *excelize.File, styleID int, resolved resolvedCellFormat, customNumFmt *string) {
+ if customNumFmt != nil || f.Styles.CellXfs == nil || styleID < 0 || styleID >= len(f.Styles.CellXfs.Xf) {
+ return
+ }
+ cellXF := f.Styles.CellXfs.Xf[styleID]
+ if cellXF.NumFmtID == nil || *cellXF.NumFmtID != resolved.NumFmtID {
+ // A named-style XF can supply the effective ID. Its custom code is
+ // retained above; do not infer currency metadata from format text.
+ return
+ }
+ getter, ok := any(f).(excelizeStyleGetter)
+ if !ok {
+ return
+ }
+ nativeStyle, err := getter.GetStyle(styleID)
+ if err != nil || nativeStyle == nil {
+ return
+ }
+ if decimalPlaces, ok := excelizePublicFieldValue(nativeStyle, "DecimalPlaces"); ok {
+ setExcelizeField(style, "DecimalPlaces", decimalPlaces)
+ }
+ if negativeRed, ok := excelizePublicFieldValue(nativeStyle, "NegRed"); ok {
+ setExcelizeField(style, "NegRed", negativeRed)
+ }
+}
+
+func excelizePublicFieldValue(target any, name string) (any, bool) {
+ ref := reflect.ValueOf(target)
+ if !ref.IsValid() {
+ return nil, false
+ }
+ if ref.Kind() == reflect.Ptr {
+ if ref.IsNil() {
+ return nil, false
+ }
+ ref = ref.Elem()
+ }
+ field := ref.FieldByName(name)
+ if !field.IsValid() {
+ return nil, false
+ }
+ if field.Kind() == reflect.Ptr {
+ if field.IsNil() {
+ return nil, false
+ }
+ field = field.Elem()
+ }
+ return field.Interface(), true
+}
+
+type xlsxColor struct {
+ Auto bool `xml:"auto,attr,omitempty"`
+ RGB string `xml:"rgb,attr,omitempty"`
+ Indexed int `xml:"indexed,attr,omitempty"`
+ Theme *int `xml:"theme,attr"`
+ Tint float64 `xml:"tint,attr,omitempty"`
+}
+
+func getCellFillColor(color *xlsxColor, themeColors []string, indexedColors map[int]string) []string {
+ if color == nil || color.Auto {
+ return nil
+ }
+
+ rgb := color.RGB
+ if color.Theme != nil {
+ index := *color.Theme
+ if index < 0 || index >= len(themeColors) {
+ return nil
+ }
+ rgb = themeColors[index]
+ } else if rgb == "" {
+ rgb = indexedColor(indexedColors, color.Indexed)
+ }
+
+ rgb = normalizeRGB(rgb)
+ if rgb == "" {
+ return nil
+ }
+ if color.Tint != 0 {
+ rgb = normalizeRGB(excelize.ThemeColor(strings.TrimPrefix(rgb, "#"), color.Tint))
+ }
+ return []string{rgb}
+}
+
+func normalizeRGB(rgb string) string {
+ rgb = strings.TrimPrefix(strings.ToUpper(rgb), "#")
+ if len(rgb) == 8 {
+ rgb = rgb[2:]
+ }
+ if len(rgb) != 6 {
+ return ""
+ }
+ return "#" + rgb
+}
+
+func indexedColor(indexedColors map[int]string, index int) string {
+ if index < 0 {
+ return ""
+ }
+ if color, ok := indexedColors[index]; ok {
+ return color
+ }
+ if index < len(indexedColorMapping) {
+ return indexedColorMapping[index]
+ }
+ return ""
+}
+
+func readStyleMetadata(buffer bytes.Buffer) ([]string, map[int]string, map[int]string) {
+ reader, err := zip.NewReader(bytes.NewReader(buffer.Bytes()), int64(buffer.Len()))
+ if err != nil {
+ return nil, nil, nil
+ }
+
+ var themeColors []string
+ var numberFormats map[int]string
+ var indexedColors map[int]string
+ for _, entry := range reader.File {
+ if entry.Name != "xl/theme/theme1.xml" && entry.Name != "xl/styles.xml" {
+ continue
+ }
+ file, err := entry.Open()
+ if err != nil {
+ continue
+ }
+ data, readErr := io.ReadAll(file)
+ _ = file.Close()
+ if readErr != nil {
+ continue
+ }
+ switch entry.Name {
+ case "xl/theme/theme1.xml":
+ themeColors = parseThemeColors(data)
+ case "xl/styles.xml":
+ numberFormats = parseNumberFormats(data)
+ indexedColors = parseIndexedColors(data)
+ }
+ }
+ return themeColors, numberFormats, indexedColors
+}
+
+func parseThemeColors(data []byte) []string {
+ type colorChoice struct {
+ SysColor *struct {
+ LastColor string `xml:"lastClr,attr"`
+ } `xml:"sysClr"`
+ SRGBColor *struct {
+ Value string `xml:"val,attr"`
+ } `xml:"srgbClr"`
+ }
+ var theme struct {
+ Elements struct {
+ Scheme struct {
+ Dk1 colorChoice `xml:"dk1"`
+ Lt1 colorChoice `xml:"lt1"`
+ Dk2 colorChoice `xml:"dk2"`
+ Lt2 colorChoice `xml:"lt2"`
+ Accent1 colorChoice `xml:"accent1"`
+ Accent2 colorChoice `xml:"accent2"`
+ Accent3 colorChoice `xml:"accent3"`
+ Accent4 colorChoice `xml:"accent4"`
+ Accent5 colorChoice `xml:"accent5"`
+ Accent6 colorChoice `xml:"accent6"`
+ Hlink colorChoice `xml:"hlink"`
+ FolHlink colorChoice `xml:"folHlink"`
+ } `xml:"clrScheme"`
+ } `xml:"themeElements"`
+ }
+ if xml.Unmarshal(data, &theme) != nil {
+ return nil
+ }
+ choices := []colorChoice{
+ theme.Elements.Scheme.Lt1, theme.Elements.Scheme.Dk1,
+ theme.Elements.Scheme.Lt2, theme.Elements.Scheme.Dk2,
+ theme.Elements.Scheme.Accent1, theme.Elements.Scheme.Accent2,
+ theme.Elements.Scheme.Accent3, theme.Elements.Scheme.Accent4,
+ theme.Elements.Scheme.Accent5, theme.Elements.Scheme.Accent6,
+ theme.Elements.Scheme.Hlink, theme.Elements.Scheme.FolHlink,
+ }
+ colors := make([]string, len(choices))
+ for index, choice := range choices {
+ switch {
+ case choice.SysColor != nil:
+ colors[index] = choice.SysColor.LastColor
+ case choice.SRGBColor != nil:
+ colors[index] = choice.SRGBColor.Value
+ }
+ }
+ return colors
+}
+
+func parseNumberFormats(data []byte) map[int]string {
+ type numberFormat struct {
+ ID int `xml:"numFmtId,attr"`
+ FormatCode string `xml:"formatCode,attr"`
+ FormatCode16 string `xml:"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main formatCode16,attr"`
+ }
+ var formats struct {
+ NumFmts struct {
+ NumFmt []numberFormat `xml:"numFmt"`
+ } `xml:"numFmts"`
+ }
+ if xml.Unmarshal(data, &formats) != nil {
+ return nil
+ }
+ result := make(map[int]string, len(formats.NumFmts.NumFmt))
+ for _, format := range formats.NumFmts.NumFmt {
+ code := format.FormatCode16
+ if code == "" {
+ code = format.FormatCode
+ }
+ if code != "" {
+ result[format.ID] = code
+ }
+ }
+ return result
+}
+
+func parseIndexedColors(data []byte) map[int]string {
+ var styles struct {
+ Colors struct {
+ IndexedColors struct {
+ RGBColors []struct {
+ RGB string `xml:"rgb,attr"`
+ } `xml:"rgbColor"`
+ } `xml:"indexedColors"`
+ } `xml:"colors"`
+ }
+ if xml.Unmarshal(data, &styles) != nil {
+ return nil
+ }
+ colors := make(map[int]string, len(styles.Colors.IndexedColors.RGBColors))
+ for index, color := range styles.Colors.IndexedColors.RGBColors {
+ colors[index] = color.RGB
+ }
+ return colors
+}
+
+var indexedColorMapping = []string{
+ "000000", "FFFFFF", "FF0000", "00FF00", "0000FF", "FFFF00", "FF00FF", "00FFFF",
+ "000000", "FFFFFF", "FF0000", "00FF00", "0000FF", "FFFF00", "FF00FF", "00FFFF",
+ "800000", "008000", "000080", "808000", "800080", "008080", "C0C0C0", "808080",
+ "9999FF", "993366", "FFFFCC", "CCFFFF", "660066", "FF8080", "0066CC", "CCCCFF",
+ "000080", "FF00FF", "FFFF00", "00FFFF", "800080", "800000", "008080", "0000FF",
+ "00CCFF", "CCFFFF", "CCFFCC", "FFFF99", "99CCFF", "FF99CC", "CC99FF", "FFCC99",
+ "3366FF", "33CCCC", "99CC00", "FFCC00", "FF9900", "FF6600", "666699", "969696",
+ "003366", "339966", "003300", "333300", "993300", "993366", "333399", "333333",
+ "000000", "FFFFFF",
+}
diff --git a/excelizeutil/excelizeutil_test.go b/excelizeutil/excelizeutil_test.go
new file mode 100644
index 0000000..16644d5
--- /dev/null
+++ b/excelizeutil/excelizeutil_test.go
@@ -0,0 +1,566 @@
+package excelizeutil
+
+import (
+ "archive/zip"
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "regexp"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/xuri/excelize/v2"
+)
+
+func workbookWithStyle(t *testing.T, style *excelize.Style) bytes.Buffer {
+ t.Helper()
+
+ f := excelize.NewFile()
+ t.Cleanup(func() { require.NoError(t, f.Close()) })
+
+ styleID, err := f.NewStyle(style)
+ require.NoError(t, err)
+ require.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", styleID))
+
+ buffer, err := f.WriteToBuffer()
+ require.NoError(t, err)
+ return *buffer
+}
+
+func mustGetStyle(t *testing.T, buffer bytes.Buffer, sheetName string, corIdx, rowIdx int) excelize.Style {
+ t.Helper()
+ style, err := GetStyle(buffer, sheetName, corIdx, rowIdx)
+ require.NoError(t, err)
+ return style
+}
+
+func TestGetStyleReturnsOpenReaderError(t *testing.T) {
+ _, err := GetStyle(bytes.Buffer{}, "Sheet1", 1, 1)
+ require.Error(t, err)
+ assert.Contains(t, err.Error(), "open workbook")
+}
+
+func TestGetStyleReturnsTruncatedWorkbookError(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{})
+ truncated := append([]byte(nil), buffer.Bytes()[:buffer.Len()-22]...)
+
+ _, err := GetStyle(*bytes.NewBuffer(truncated), "Sheet1", 1, 1)
+ require.Error(t, err)
+ assert.True(t, errors.Is(err, zip.ErrFormat), "GetStyle should preserve the ZIP format error")
+ assert.Contains(t, err.Error(), "open workbook")
+}
+
+func TestGetStyleReturnsCoordinateError(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{})
+ for _, coordinates := range [][2]int{{0, 1}, {1, 0}} {
+ _, err := GetStyle(buffer, "Sheet1", coordinates[0], coordinates[1])
+ require.Error(t, err)
+ assert.Contains(t, err.Error(), "convert cell coordinates")
+ }
+}
+
+func TestGetStyleReturnsGetCellStyleError(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{})
+ _, err := GetStyle(buffer, "Missing", 1, 1)
+ require.Error(t, err)
+ assert.Contains(t, err.Error(), "get cell style")
+}
+
+func TestGetStyleReturnsInvalidCellStyleIDError(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{Font: &excelize.Font{Bold: true}})
+ buffer = rewriteXLSXEntry(t, buffer, "xl/worksheets/sheet1.xml", func(data []byte) []byte {
+ old := []byte(`s="1"`)
+ require.Contains(t, string(data), string(old))
+ return bytes.Replace(data, old, []byte(`s="999"`), 1)
+ })
+
+ _, err := GetStyle(buffer, "Sheet1", 1, 1)
+ require.ErrorIs(t, err, errInvalidStyleReference)
+}
+
+func TestGetStyleReturnsInvalidStyleReferenceError(t *testing.T) {
+ format := `yyyy-mm-dd`
+ style := &excelize.Style{
+ Font: &excelize.Font{Bold: true},
+ Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#123456"}},
+ Border: []excelize.Border{{Type: "top", Style: 1}},
+ CustomNumFmt: &format,
+ }
+ tests := []struct {
+ name string
+ attribute string
+ }{
+ {name: "font ID", attribute: "fontId"},
+ {name: "fill ID", attribute: "fillId"},
+ {name: "border ID", attribute: "borderId"},
+ {name: "custom number format ID", attribute: "numFmtId"},
+ {name: "named style XF ID", attribute: "xfId"},
+ }
+
+ for _, test := range tests {
+ for _, invalidID := range []int{-1, 999} {
+ t.Run(fmt.Sprintf("%s/%d", test.name, invalidID), func(t *testing.T) {
+ buffer := workbookWithStyle(t, style)
+ buffer = rewriteCellXFAttribute(t, buffer, test.attribute, invalidID)
+
+ _, err := GetStyle(buffer, "Sheet1", 1, 1)
+ require.ErrorIs(t, err, errInvalidStyleReference)
+ assert.Contains(t, err.Error(), "resolve cell style")
+ })
+ }
+ }
+}
+
+func TestGetStylePreservesPatternFill(t *testing.T) {
+ tests := []struct {
+ name string
+ pattern int
+ }{
+ {name: "solid", pattern: 1},
+ {name: "dark horizontal", pattern: 5},
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{
+ Fill: excelize.Fill{
+ Type: "pattern",
+ Pattern: test.pattern,
+ Color: []string{"#315D3C"},
+ },
+ })
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1).Fill
+ assert.Equal(t, "pattern", got.Type)
+ assert.Equal(t, test.pattern, got.Pattern)
+ assert.Equal(t, []string{"#315D3C"}, got.Color)
+ })
+ }
+}
+
+func TestGetStylePreservesFullStyle(t *testing.T) {
+ tests := []struct {
+ name string
+ style *excelize.Style
+ check func(*testing.T, excelize.Style)
+ }{
+ {
+ name: "built in number format and style fields",
+ style: &excelize.Style{
+ Font: &excelize.Font{
+ Bold: true,
+ Italic: true,
+ Underline: "single",
+ Family: "Aptos",
+ Size: 11,
+ Strike: true,
+ Color: "#123456",
+ },
+ Alignment: &excelize.Alignment{
+ Horizontal: "center",
+ Indent: 2,
+ JustifyLastLine: true,
+ ReadingOrder: 1,
+ RelativeIndent: 3,
+ ShrinkToFit: true,
+ TextRotation: 45,
+ Vertical: "center",
+ WrapText: true,
+ },
+ Protection: &excelize.Protection{Hidden: true, Locked: false},
+ NumFmt: 14,
+ },
+ check: func(t *testing.T, got excelize.Style) {
+ require.NotNil(t, got.Font)
+ wantFont := &excelize.Font{
+ Bold: true, Italic: true, Underline: "single", Family: "Aptos",
+ Size: 11, Strike: true, Color: "#123456",
+ }
+ setPublicField(wantFont, "ColorIndexed", -1)
+ assert.Equal(t, wantFont, got.Font)
+ assert.Equal(t, &excelize.Alignment{
+ Horizontal: "center", Indent: 2, JustifyLastLine: true,
+ ReadingOrder: 1, RelativeIndent: 3, ShrinkToFit: true,
+ TextRotation: 45, Vertical: "center", WrapText: true,
+ }, got.Alignment)
+ assert.Equal(t, &excelize.Protection{Hidden: true, Locked: false}, got.Protection)
+ assert.Equal(t, 14, got.NumFmt)
+ },
+ },
+ {
+ name: "custom number format",
+ style: func() *excelize.Style {
+ format := `yyyy-mm-dd "date"`
+ return &excelize.Style{CustomNumFmt: &format}
+ }(),
+ check: func(t *testing.T, got excelize.Style) {
+ require.NotNil(t, got.CustomNumFmt)
+ assert.Equal(t, `yyyy-mm-dd "date"`, *got.CustomNumFmt)
+ },
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ buffer := workbookWithStyle(t, test.style)
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1)
+ test.check(t, got)
+ reapplied := workbookWithStyle(t, &got)
+ test.check(t, mustGetStyle(t, reapplied, "Sheet1", 1, 1))
+ })
+ }
+}
+
+func TestGetStyleInheritsNamedStyleXF(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{NumFmt: 14})
+ buffer = rewriteXLSXEntry(t, buffer, "xl/styles.xml", func([]byte) []byte {
+ data := []byte(namedStyleStylesXML)
+ oldChild := []byte(``)
+ require.Equal(t, 1, bytes.Count(data, oldChild))
+ return bytes.Replace(data, oldChild, []byte(``), 1)
+ })
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1)
+ require.Equal(t, 14, got.NumFmt)
+ wantFont := &excelize.Font{
+ Bold: true, Italic: true, Underline: "single", Family: "Aptos",
+ Size: 14, Color: "#123456",
+ }
+ setPublicField(wantFont, "ColorIndexed", -1)
+ require.NotNil(t, got.Font)
+ assert.Equal(t, wantFont, got.Font)
+ assert.Equal(t, excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#315D3C"}}, got.Fill)
+ assert.ElementsMatch(t, []excelize.Border{
+ {Type: "left", Style: 1, Color: "#111111"},
+ {Type: "right", Style: 2, Color: "#222222"},
+ }, got.Border)
+ assert.Equal(t, &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, got.Alignment)
+ assert.Equal(t, &excelize.Protection{Locked: false, Hidden: true}, got.Protection)
+
+ reapplied := workbookWithStyle(t, &got)
+ reread := mustGetStyle(t, reapplied, "Sheet1", 1, 1)
+ assert.Equal(t, got.Alignment, reread.Alignment)
+ assert.Equal(t, got.Protection, reread.Protection)
+ assert.Equal(t, styleAlignmentXML(t, reapplied), alignmentStyleXML{
+ Horizontal: "center", Vertical: "center", WrapText: "true",
+ })
+ protection := styleProtectionXML(t, reapplied)
+ assertXMLBool(t, protection.Locked, false)
+ assertXMLBool(t, protection.Hidden, true)
+}
+
+func TestGetStyleInheritsCustomizedFontZeroWhenChildDoesNotApplyFont(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{NumFmt: 14})
+ buffer = rewriteXLSXEntry(t, buffer, "xl/styles.xml", func([]byte) []byte {
+ data := []byte(namedStyleStylesXML)
+ oldFont := []byte(``)
+ newFont := []byte(``)
+ require.Equal(t, 1, bytes.Count(data, oldFont))
+ data = bytes.Replace(data, oldFont, newFont, 1)
+ oldParent := []byte(`numFmtId="14" fontId="1"`)
+ require.Equal(t, 1, bytes.Count(data, oldParent))
+ data = bytes.Replace(data, oldParent, []byte(`numFmtId="14" fontId="0"`), 1)
+ oldChild := []byte(``)
+ require.Equal(t, 1, bytes.Count(data, oldChild))
+ return bytes.Replace(data, oldChild, []byte(``), 1)
+ })
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1)
+ require.NotNil(t, got.Font, "fontId=0 on the parent XF remains effective when the child explicitly inherits it")
+ assert.True(t, got.Font.Bold)
+ assert.Equal(t, float64(15), got.Font.Size)
+ assert.Equal(t, "InheritedZero", got.Font.Family)
+
+ reapplied := workbookWithStyle(t, &got)
+ reread := mustGetStyle(t, reapplied, "Sheet1", 1, 1)
+ require.NotNil(t, reread.Font)
+ assert.True(t, reread.Font.Bold)
+ assert.Equal(t, float64(15), reread.Font.Size)
+ assert.Equal(t, "InheritedZero", reread.Font.Family)
+ assert.Contains(t, xlsxEntry(t, reapplied, "xl/styles.xml"), `name val="InheritedZero"`)
+}
+
+func TestGetStyleAppliesImplicitFontZeroWhenApplyFontIsTrue(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{NumFmt: 14})
+ buffer = rewriteXLSXEntry(t, buffer, "xl/styles.xml", func([]byte) []byte {
+ data := []byte(namedStyleStylesXML)
+ oldFont := []byte(``)
+ newFont := []byte(``)
+ require.Equal(t, 1, bytes.Count(data, oldFont))
+ data = bytes.Replace(data, oldFont, newFont, 1)
+ oldChild := []byte(``)
+ require.Equal(t, 1, bytes.Count(data, oldChild))
+ return bytes.Replace(data, oldChild, []byte(``), 1)
+ })
+ assert.Contains(t, xlsxEntry(t, buffer, "xl/styles.xml"), ``)
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1)
+ require.NotNil(t, got.Font, "applyFont=true with omitted fontId applies schema-default fontId=0")
+ assert.True(t, got.Font.Bold)
+ assert.Equal(t, float64(15), got.Font.Size)
+ assert.Equal(t, "ImplicitZero", got.Font.Family)
+
+ reapplied := workbookWithStyle(t, &got)
+ reread := mustGetStyle(t, reapplied, "Sheet1", 1, 1)
+ require.NotNil(t, reread.Font)
+ assert.True(t, reread.Font.Bold)
+ assert.Equal(t, float64(15), reread.Font.Size)
+ assert.Equal(t, "ImplicitZero", reread.Font.Family)
+ assert.Contains(t, xlsxEntry(t, reapplied, "xl/styles.xml"), `name val="ImplicitZero"`)
+}
+
+func TestGetStylePreservesLocalizedBuiltInNumberFormatID(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{NumFmt: 14})
+ buffer = rewriteXLSXEntry(t, buffer, "xl/styles.xml", func(data []byte) []byte {
+ old := []byte(``)
+ return bytes.Replace(data, []byte(""), append(colors, []byte("")...), 1)
+ })
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1).Fill.Color
+ assert.Equal(t, []string{"#BEAD10"}, got)
+}
+
+func TestGetStyleResolvesDefaultIndexedOOXMLColor(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{
+ Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#123456"}},
+ })
+ buffer = rewriteXLSXEntry(t, buffer, "xl/styles.xml", func(data []byte) []byte {
+ old := []byte(`rgb="FF123456"`)
+ require.Equal(t, 1, bytes.Count(data, old))
+ return bytes.Replace(data, old, []byte(`indexed="5"`), 1)
+ })
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1).Fill.Color
+ assert.Equal(t, []string{"#FFFF00"}, got)
+}
+
+func TestGetStyleDefaultsOmittedUnderlineValueToSingle(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{Font: &excelize.Font{Underline: "single"}})
+ buffer = rewriteXLSXEntry(t, buffer, "xl/styles.xml", func(data []byte) []byte {
+ old := []byte(`val="single"`)
+ require.Equal(t, 1, bytes.Count(data, old))
+ return bytes.Replace(data, old, nil, 1)
+ })
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1).Font
+ require.NotNil(t, got)
+ assert.Equal(t, "single", got.Underline)
+}
+
+func TestGetStylePreservesAllBorderSides(t *testing.T) {
+ want := []excelize.Border{
+ {Type: "top", Style: 1, Color: "#111111"},
+ {Type: "bottom", Style: 2, Color: "#222222"},
+ {Type: "left", Style: 3, Color: "#333333"},
+ {Type: "right", Style: 4, Color: "#444444"},
+ {Type: "diagonalUp", Style: 6, Color: "#666666"},
+ {Type: "diagonalDown", Style: 6, Color: "#666666"},
+ }
+ buffer := workbookWithStyle(t, &excelize.Style{Border: want})
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1).Border
+ assert.ElementsMatch(t, want, got)
+ reapplied := workbookWithStyle(t, &excelize.Style{Border: got})
+ assert.ElementsMatch(t, want, mustGetStyle(t, reapplied, "Sheet1", 1, 1).Border)
+}
+
+func TestGetStyleResolvesThemeColorChoiceKinds(t *testing.T) {
+ tests := []struct {
+ themeIndex int
+ want string
+ }{
+ {themeIndex: 0, want: "#AABBCC"},
+ {themeIndex: 1, want: "#112233"},
+ {themeIndex: 2, want: "#DDEEFF"},
+ {themeIndex: 3, want: "#445566"},
+ {themeIndex: 4, want: "#5B9BD5"},
+ {themeIndex: 5, want: "#ED7D31"},
+ {themeIndex: 6, want: "#A5A5A5"},
+ {themeIndex: 7, want: "#FFC000"},
+ {themeIndex: 8, want: "#4472C4"},
+ {themeIndex: 9, want: "#70AD47"},
+ {themeIndex: 10, want: "#0563C1"},
+ {themeIndex: 11, want: "#954F72"},
+ }
+
+ for _, test := range tests {
+ t.Run(fmt.Sprintf("theme-%d", test.themeIndex), func(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{
+ Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#123456"}},
+ })
+ buffer = rewriteXLSXEntry(t, buffer, "xl/styles.xml", func(data []byte) []byte {
+ old := []byte(`rgb="FF123456"`)
+ newColor := []byte(fmt.Sprintf(`theme="%d"`, test.themeIndex))
+ require.Equal(t, 1, bytes.Count(data, old))
+ return bytes.Replace(data, old, newColor, 1)
+ })
+ buffer = rewriteXLSXEntry(t, buffer, "xl/theme/theme1.xml", func(data []byte) []byte {
+ replacements := [][2]string{
+ {"dk1", ``},
+ {"lt1", ``},
+ {"dk2", ``},
+ {"lt2", ``},
+ }
+ for _, replacement := range replacements {
+ pattern := regexp.MustCompile(`(?s).*?`)
+ require.Equal(t, 1, len(pattern.FindAll(data, -1)))
+ data = pattern.ReplaceAll(data, []byte(``+replacement[1]+``))
+ }
+ return data
+ })
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1)
+ require.Len(t, got.Fill.Color, 1)
+ assert.Equal(t, test.want, got.Fill.Color[0])
+ })
+ }
+}
+
+func TestGetStyleClosesLargeWorkbookTemporaryFiles(t *testing.T) {
+ tempDir, err := os.MkdirTemp("", "excelizeutil-temp-")
+ require.NoError(t, err)
+ t.Cleanup(func() { require.NoError(t, os.RemoveAll(tempDir)) })
+ t.Setenv("TMPDIR", tempDir)
+
+ f := excelize.NewFile()
+ sheet := f.GetSheetName(0)
+ longText := strings.Repeat("x", 30_000)
+ for row := 1; row <= 570; row++ {
+ value := fmt.Sprintf("%04d%s", row, longText)
+ axis := fmt.Sprintf("A%d", row)
+ require.NoError(t, f.SetCellValue(sheet, axis, value))
+ }
+ buffer, err := f.WriteToBuffer()
+ require.NoError(t, err)
+ require.NoError(t, f.Close())
+
+ _ = mustGetStyle(t, *buffer, sheet, 1, 1)
+
+ entries, err := os.ReadDir(tempDir)
+ require.NoError(t, err)
+ assert.Empty(t, entries, "GetStyle should remove Excelize temporary files")
+}
+
+func rewriteXLSXEntry(t *testing.T, buffer bytes.Buffer, name string, rewrite func([]byte) []byte) bytes.Buffer {
+ t.Helper()
+
+ reader, err := zip.NewReader(bytes.NewReader(buffer.Bytes()), int64(buffer.Len()))
+ require.NoError(t, err)
+
+ var output bytes.Buffer
+ writer := zip.NewWriter(&output)
+ found := false
+ for _, file := range reader.File {
+ contents, err := file.Open()
+ require.NoError(t, err)
+ data, err := io.ReadAll(contents)
+ require.NoError(t, err)
+ require.NoError(t, contents.Close())
+ if file.Name == name {
+ data = rewrite(data)
+ found = true
+ }
+
+ entry, err := writer.Create(file.Name)
+ require.NoError(t, err)
+ _, err = entry.Write(data)
+ require.NoError(t, err)
+ }
+ require.True(t, found, "XLSX archive did not contain %q", name)
+ require.NoError(t, writer.Close())
+ return output
+}
+
+func rewriteCellXFAttribute(t *testing.T, buffer bytes.Buffer, attribute string, value int) bytes.Buffer {
+ t.Helper()
+ return rewriteXLSXEntry(t, buffer, "xl/styles.xml", func(data []byte) []byte {
+ cellXFsStart := bytes.Index(data, []byte(""))
+ require.NotEqual(t, -1, cellXFsEnd, "cellXfs element must be closed")
+ cellXFsEnd += cellXFsStart
+ cellXFs := data[cellXFsStart:cellXFsEnd]
+
+ firstXFStart := bytes.Index(cellXFs, []byte(""))
+ require.NotEqual(t, -1, firstXFEnd, "default cell XF start tag must be closed")
+ secondXFStart := bytes.Index(cellXFs[firstXFStart+firstXFEnd+1:], []byte(""))
+ require.NotEqual(t, -1, secondXFEnd, "styled cell XF start tag must be closed")
+ secondXFEnd += secondXFStart
+
+ startTag := cellXFs[secondXFStart : secondXFEnd+1]
+ attributePattern := regexp.MustCompile(`(^|\s)` + regexp.QuoteMeta(attribute) + `="[^"]*"`)
+ location := attributePattern.FindIndex(startTag)
+ require.NotNil(t, location, "%s attribute must exist in the styled cell XF", attribute)
+ absoluteStart := cellXFsStart + secondXFStart + location[0]
+ absoluteEnd := cellXFsStart + secondXFStart + location[1]
+ replacement := []byte(fmt.Sprintf(` %s="%d"`, attribute, value))
+ result := make([]byte, 0, len(data)+len(replacement)-(absoluteEnd-absoluteStart))
+ result = append(result, data[:absoluteStart]...)
+ result = append(result, replacement...)
+ result = append(result, data[absoluteEnd:]...)
+ return result
+ })
+}
+
+const namedStyleStylesXML = `
+
+
+
+
+
+
+`
diff --git a/excelizeutil/style_enums_gen.go b/excelizeutil/style_enums_gen.go
new file mode 100644
index 0000000..b2ca492
--- /dev/null
+++ b/excelizeutil/style_enums_gen.go
@@ -0,0 +1,39 @@
+// Code generated by go generate; DO NOT EDIT.
+
+package excelizeutil
+
+import "github.com/tomtwinkle/excelizeam/excelizestyle"
+
+type fillPattern = excelizestyle.FillPattern
+
+const fillPatternNone = excelizestyle.FillPatternNone
+
+func parseFillPattern(value string) (fillPattern, bool) { return excelizestyle.ParseFillPattern(value) }
+
+type borderStyle = excelizestyle.BorderStyle
+
+const borderStyleNone = excelizestyle.BorderStyleNone
+
+func parseBorderStyle(value string) (borderStyle, bool) { return excelizestyle.ParseBorderStyle(value) }
+
+func gradientGeometries() []gradientGeometry {
+ return []gradientGeometry{
+ {typeName: "", degree: 90, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "", degree: 270, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "", degree: 90, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 0.5, 1}},
+ {typeName: "", degree: 0, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "", degree: 180, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "", degree: 0, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 0.5, 1}},
+ {typeName: "", degree: 45, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "", degree: 255, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "", degree: 45, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 0.5, 1}},
+ {typeName: "", degree: 135, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "", degree: 315, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "", degree: 135, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 0.5, 1}},
+ {typeName: "path", degree: 0, left: 0, right: 0, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "path", degree: 0, left: 1, right: 1, top: 0, bottom: 0, positions: []float64{0, 1}},
+ {typeName: "path", degree: 0, left: 0, right: 0, top: 1, bottom: 1, positions: []float64{0, 1}},
+ {typeName: "path", degree: 0, left: 1, right: 1, top: 1, bottom: 1, positions: []float64{0, 1}},
+ {typeName: "path", degree: 0, left: 0.5, right: 0.5, top: 0.5, bottom: 0.5, positions: []float64{0, 1}},
+ }
+}
diff --git a/excelizeutil/style_roundtrip_test.go b/excelizeutil/style_roundtrip_test.go
new file mode 100644
index 0000000..c6b8771
--- /dev/null
+++ b/excelizeutil/style_roundtrip_test.go
@@ -0,0 +1,671 @@
+package excelizeutil
+
+import (
+ "archive/zip"
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "io"
+ "reflect"
+ "regexp"
+ "sort"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/tomtwinkle/excelizeam/excelizestyle"
+ "github.com/xuri/excelize/v2"
+)
+
+func TestExcelizeV2101StyleFieldInventory(t *testing.T) {
+ styleFields := publicFieldNames(reflect.TypeOf(excelize.Style{}))
+ fontFields := publicFieldNames(reflect.TypeOf(excelize.Font{}))
+ fillFields := publicFieldNames(reflect.TypeOf(excelize.Fill{}))
+ if !containsString(styleFields, "DecimalPlaces") || !containsString(fontFields, "ColorTheme") {
+ t.Skip("the linked Excelize version predates the v2.10.1 Style API")
+ }
+
+ assert.Equal(t, []string{"Alignment", "Border", "CustomNumFmt", "DecimalPlaces", "Fill", "Font", "NegRed", "NumFmt", "Protection"}, styleFields)
+ assert.Equal(t, []string{"Bold", "Charset", "Color", "ColorIndexed", "ColorTheme", "ColorTint", "Family", "Italic", "Size", "Strike", "Underline", "VertAlign"}, fontFields)
+ assert.Equal(t, []string{"Color", "Pattern", "Shading", "Transparency", "Type"}, fillFields)
+ assert.Equal(t, []string{"Color", "Style", "Type"}, publicFieldNames(reflect.TypeOf(excelize.Border{})))
+ assert.Equal(t, []string{"Hidden", "Locked"}, publicFieldNames(reflect.TypeOf(excelize.Protection{})))
+ assert.Equal(t, []string{"Horizontal", "Indent", "JustifyLastLine", "ReadingOrder", "RelativeIndent", "ShrinkToFit", "TextRotation", "Vertical", "WrapText"}, publicFieldNames(reflect.TypeOf(excelize.Alignment{})))
+}
+
+func TestGetStyleRoundTripsAllGradientPresets(t *testing.T) {
+ for shading := 0; shading < int(excelizestyle.GradientShadingCount); shading++ {
+ t.Run(fmt.Sprintf("shading-%d", shading), func(t *testing.T) {
+ style := &excelize.Style{Fill: excelize.Fill{Type: "gradient", Shading: shading, Color: []string{"#123456", "#ABCDEF"}}}
+ original := workbookWithStyle(t, style)
+ got := mustGetStyle(t, original, "Sheet1", 1, 1)
+ require.Equal(t, "gradient", got.Fill.Type)
+ require.Equal(t, shading, got.Fill.Shading)
+ require.Equal(t, []string{"#123456", "#ABCDEF"}, got.Fill.Color)
+
+ reapplied := workbookWithStyle(t, &got)
+ reread := mustGetStyle(t, reapplied, "Sheet1", 1, 1)
+ assert.Equal(t, got.Fill, reread.Fill)
+ assert.Equal(t, styleGradientXML(t, original), styleGradientXML(t, reapplied), "the saved OOXML gradient geometry and stops must survive reapplication")
+ })
+ }
+}
+
+func TestGetStyleRoundTripsEveryPublicFontField(t *testing.T) {
+ if !hasPublicField(reflect.TypeOf(excelize.Font{}), "ColorTheme") {
+ t.Skip("the linked Excelize version predates the v2.10.1 Font API")
+ }
+ tests := []struct {
+ name string
+ field string
+ value any
+ want any
+ xmlMarker string
+ }{
+ {name: "Bold", field: "Bold", value: true, want: true, xmlMarker: `"))
+ require.NotEqual(t, -1, fontStart)
+ fontEnd := bytes.Index(data[fontStart:], []byte(""))
+ require.NotEqual(t, -1, fontEnd)
+ fontEnd += fontStart + len("")
+ font := append([]byte(nil), data[fontStart:fontEnd]...)
+ font = bytes.Replace(font, []byte(""), []byte(""), 1)
+ data = append(append(append([]byte(nil), data[:fontStart]...), font...), data[fontEnd:]...)
+ oldXF := []byte(`fontId="1"`)
+ require.Equal(t, 1, bytes.Count(data, oldXF))
+ return bytes.Replace(data, oldXF, []byte(`fontId="0" applyFont="1"`), 1)
+ })
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1)
+ require.NotNil(t, got.Font, "an explicitly applied fontId=0 is a real style, not an absent font")
+ assert.True(t, got.Font.Bold, "an empty means true")
+ assert.True(t, got.Font.Italic, "an empty means true")
+ assert.True(t, got.Font.Strike, "an empty means true")
+ assert.Contains(t, xlsxEntry(t, buffer, "xl/styles.xml"), `applyFont="1"`)
+}
+
+func TestGetStyleHandlesSparseBorderXML(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{Border: []excelize.Border{{Type: "top", Style: 1, Color: "#112233"}}})
+ buffer = rewriteXLSXEntry(t, buffer, "xl/styles.xml", func(data []byte) []byte {
+ data = bytes.Replace(data, []byte(``), nil, 1)
+ data = bytes.Replace(data, []byte(``), nil, 1)
+ return data
+ })
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1)
+ assert.Equal(t, []excelize.Border{{Type: "top", Style: 1, Color: "#112233"}}, got.Border)
+ assert.Equal(t, got.Border, mustGetStyle(t, workbookWithStyle(t, &got), "Sheet1", 1, 1).Border)
+}
+
+func TestGetStyleUsesForegroundColorWhenPatternHasBothColors(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{Fill: excelize.Fill{Type: "pattern", Pattern: 10, Color: []string{"#123456"}}})
+ buffer = rewriteXLSXEntry(t, buffer, "xl/styles.xml", func(data []byte) []byte {
+ patternPosition := bytes.Index(data, []byte(`patternType="darkTrellis"`))
+ require.NotEqual(t, -1, patternPosition)
+ fillClose := bytes.Index(data[patternPosition:], []byte(``))
+ require.NotEqual(t, -1, fillClose)
+ fillClose += patternPosition
+ data = append(append(append([]byte(nil), data[:fillClose]...), []byte(``)...), data[fillClose:]...)
+ return data
+ })
+
+ got := mustGetStyle(t, buffer, "Sheet1", 1, 1)
+ assert.Equal(t, []string{"#123456"}, got.Fill.Color)
+ reapplied := workbookWithStyle(t, &got)
+ assert.Equal(t, []string{"#123456"}, mustGetStyle(t, reapplied, "Sheet1", 1, 1).Fill.Color)
+ assert.NotContains(t, xlsxEntry(t, reapplied, "xl/styles.xml"), `FFABCDEF`, "Style.Fill has only one color and cannot encode both pattern colors")
+}
+
+func TestGetStyleRoundTripsEveryPatternIDAndBorderStyle(t *testing.T) {
+ for pattern := 0; pattern < int(excelizestyle.FillPatternCount); pattern++ {
+ t.Run(fmt.Sprintf("pattern-%d", pattern), func(t *testing.T) {
+ style := &excelize.Style{Fill: excelize.Fill{Type: "pattern", Pattern: pattern, Color: []string{"#315D3C"}}}
+ got := mustGetStyle(t, workbookWithStyle(t, style), "Sheet1", 1, 1)
+ require.Equal(t, "pattern", got.Fill.Type)
+ assert.Equal(t, pattern, got.Fill.Pattern)
+ assert.Equal(t, []string{"#315D3C"}, got.Fill.Color)
+ reapplied := workbookWithStyle(t, &got)
+ assert.Equal(t, got.Fill, mustGetStyle(t, reapplied, "Sheet1", 1, 1).Fill)
+ })
+ }
+ for borderStyle := 0; borderStyle < int(excelizestyle.BorderStyleCount); borderStyle++ {
+ t.Run(fmt.Sprintf("border-style-%d", borderStyle), func(t *testing.T) {
+ style := &excelize.Style{Border: []excelize.Border{{Type: "top", Style: borderStyle, Color: "#112233"}}}
+ got := mustGetStyle(t, workbookWithStyle(t, style), "Sheet1", 1, 1)
+ require.Equal(t, style.Border, got.Border)
+ reapplied := workbookWithStyle(t, &got)
+ assert.Equal(t, got.Border, mustGetStyle(t, reapplied, "Sheet1", 1, 1).Border)
+ })
+ }
+}
+
+func TestGetStylePreservesNumberFormatIntentWithoutGuessingFormatTokens(t *testing.T) {
+ if !hasPublicField(reflect.TypeOf(excelize.Style{}), "DecimalPlaces") {
+ t.Skip("the linked Excelize version predates the v2.10.1 Style API")
+ }
+
+ // A custom code contains the decimal count and negative-red section already.
+ // Keep its exact spelling; do not derive fields by scanning punctuation that
+ // could be quoted or escaped.
+ code := `"$"#,##0.000;[Red]("$"#,##0.000)`
+ style := &excelize.Style{NumFmt: 164, CustomNumFmt: &code, NegRed: true}
+ require.True(t, setPublicField(style, "DecimalPlaces", 3))
+ original := workbookWithStyle(t, style)
+ got := mustGetStyle(t, original, "Sheet1", 1, 1)
+ require.NotNil(t, got.CustomNumFmt)
+ assert.Equal(t, code, *got.CustomNumFmt)
+ reapplied := workbookWithStyle(t, &got)
+ reread := mustGetStyle(t, reapplied, "Sheet1", 1, 1)
+ require.NotNil(t, reread.CustomNumFmt)
+ assert.Equal(t, code, *reread.CustomNumFmt)
+ assert.Contains(t, customNumberFormats(t, reapplied), code)
+}
+
+func TestGetStyleMapsBuiltInDecimalPlacesField(t *testing.T) {
+ field, ok := reflect.TypeOf(excelize.Style{}).FieldByName("DecimalPlaces")
+ if !ok || field.Type.Kind() != reflect.Ptr {
+ t.Skip("the linked Excelize version predates the v2.10.1 DecimalPlaces API")
+ }
+ style := &excelize.Style{NumFmt: 44}
+ original := workbookWithStyle(t, style)
+ got := mustGetStyle(t, original, "Sheet1", 1, 1)
+ assert.Equal(t, 44, got.NumFmt)
+ assert.Equal(t, 2, publicFieldValue(&got, "DecimalPlaces"))
+ assert.Nil(t, got.CustomNumFmt)
+
+ reapplied := workbookWithStyle(t, &got)
+ reread := mustGetStyle(t, reapplied, "Sheet1", 1, 1)
+ assert.Equal(t, 44, reread.NumFmt)
+ assert.Equal(t, 2, publicFieldValue(&reread, "DecimalPlaces"))
+}
+
+type gradientFillXML struct {
+ Type string `xml:"type,attr"`
+ Degree float64 `xml:"degree,attr"`
+ Left float64 `xml:"left,attr"`
+ Right float64 `xml:"right,attr"`
+ Top float64 `xml:"top,attr"`
+ Bottom float64 `xml:"bottom,attr"`
+ Stops []gradientStopXML `xml:"stop"`
+}
+
+type fontColorXML struct {
+ RGB string `xml:"rgb,attr"`
+ Auto bool `xml:"auto,attr"`
+ Indexed *int `xml:"indexed,attr"`
+ Theme *int `xml:"theme,attr"`
+ Tint float64 `xml:"tint,attr"`
+}
+
+type alignmentStyleXML struct {
+ Horizontal string `xml:"horizontal,attr"`
+ Indent string `xml:"indent,attr"`
+ JustifyLastLine string `xml:"justifyLastLine,attr"`
+ ReadingOrder string `xml:"readingOrder,attr"`
+ RelativeIndent string `xml:"relativeIndent,attr"`
+ ShrinkToFit string `xml:"shrinkToFit,attr"`
+ TextRotation string `xml:"textRotation,attr"`
+ Vertical string `xml:"vertical,attr"`
+ WrapText string `xml:"wrapText,attr"`
+}
+
+type protectionStyleXML struct {
+ Locked *string `xml:"locked,attr"`
+ Hidden *string `xml:"hidden,attr"`
+}
+
+type cellXFStyleXML struct {
+ Alignment *alignmentStyleXML `xml:"alignment"`
+ Protection *protectionStyleXML `xml:"protection"`
+}
+
+func cellXFStylesXML(t *testing.T, buffer bytes.Buffer) []cellXFStyleXML {
+ t.Helper()
+ var styles struct {
+ CellXFs struct {
+ XFs []cellXFStyleXML `xml:"xf"`
+ } `xml:"cellXfs"`
+ }
+ require.NoError(t, xml.Unmarshal([]byte(xlsxEntry(t, buffer, "xl/styles.xml")), &styles))
+ return styles.CellXFs.XFs
+}
+
+func styleAlignmentXML(t *testing.T, buffer bytes.Buffer) alignmentStyleXML {
+ t.Helper()
+ var alignments []alignmentStyleXML
+ for _, xf := range cellXFStylesXML(t, buffer) {
+ if xf.Alignment != nil {
+ alignments = append(alignments, *xf.Alignment)
+ }
+ }
+ require.Len(t, alignments, 1)
+ return alignments[0]
+}
+
+func styleProtectionXML(t *testing.T, buffer bytes.Buffer) protectionStyleXML {
+ t.Helper()
+ var protections []protectionStyleXML
+ for _, xf := range cellXFStylesXML(t, buffer) {
+ if xf.Protection != nil {
+ protections = append(protections, *xf.Protection)
+ }
+ }
+ require.Len(t, protections, 1)
+ return protections[0]
+}
+
+func assertXMLBool(t *testing.T, value *string, want bool) {
+ t.Helper()
+ require.NotNil(t, value)
+ var got bool
+ switch strings.ToLower(*value) {
+ case "1", "true":
+ got = true
+ case "0", "false":
+ got = false
+ default:
+ t.Fatalf("unsupported XML boolean value %q", *value)
+ }
+ assert.Equal(t, want, got)
+}
+
+func stripProtectionAttributes(t *testing.T, data []byte) []byte {
+ t.Helper()
+ openingTag := regexp.MustCompile(`]*>`).Find(data)
+ require.NotEmpty(t, openingTag, "fixture must contain a protection element")
+ require.NotContains(t, string(openingTag), `/>`, "fixture must retain an explicit empty protection element")
+ stripped := regexp.MustCompile(`\s+(?:locked|hidden)="[^"]*"`).ReplaceAll(openingTag, nil)
+ require.NotEqual(t, string(openingTag), string(stripped), "fixture must contain explicit protection attributes")
+ return bytes.Replace(data, openingTag, []byte(``), 1)
+}
+
+func assertProtectionAttrsOmitted(t *testing.T, protection protectionStyleXML) {
+ t.Helper()
+ assert.Nil(t, protection.Locked)
+ assert.Nil(t, protection.Hidden)
+}
+
+func styleFontColors(t *testing.T, buffer bytes.Buffer) []fontColorXML {
+ t.Helper()
+ var styles struct {
+ Fonts struct {
+ Font []struct {
+ Color *fontColorXML `xml:"color"`
+ } `xml:"font"`
+ } `xml:"fonts"`
+ }
+ require.NoError(t, xml.Unmarshal([]byte(xlsxEntry(t, buffer, "xl/styles.xml")), &styles))
+ colors := make([]fontColorXML, 0, len(styles.Fonts.Font))
+ for _, font := range styles.Fonts.Font {
+ if font.Color != nil {
+ colors = append(colors, *font.Color)
+ }
+ }
+ return colors
+}
+
+func resolvedFontColor(t *testing.T, buffer bytes.Buffer, fontIndex int) []string {
+ t.Helper()
+ colors := styleFontColors(t, buffer)
+ require.Greater(t, fontIndex, -1)
+ require.Less(t, fontIndex, len(colors))
+ color := colors[fontIndex]
+ themeColors, _, indexedColors := readStyleMetadata(buffer)
+ selector := &xlsxColor{Auto: color.Auto, RGB: color.RGB, Tint: color.Tint}
+ if color.Indexed != nil {
+ selector.Indexed = *color.Indexed
+ }
+ if color.Theme != nil {
+ selector.Theme = color.Theme
+ }
+ return getCellFillColor(selector, themeColors, indexedColors)
+}
+
+type gradientStopXML struct {
+ Position float64 `xml:"position,attr"`
+ Color struct {
+ RGB string `xml:"rgb,attr"`
+ Indexed int `xml:"indexed,attr"`
+ Theme *int `xml:"theme,attr"`
+ Tint float64 `xml:"tint,attr"`
+ } `xml:"color"`
+}
+
+func styleGradientXML(t *testing.T, buffer bytes.Buffer) []gradientFillXML {
+ t.Helper()
+ data := []byte(xlsxEntry(t, buffer, "xl/styles.xml"))
+ var styles struct {
+ Fills struct {
+ Fill []struct {
+ Gradient *gradientFillXML `xml:"gradientFill"`
+ } `xml:"fill"`
+ } `xml:"fills"`
+ }
+ require.NoError(t, xml.Unmarshal(data, &styles))
+ var result []gradientFillXML
+ for _, fill := range styles.Fills.Fill {
+ if fill.Gradient != nil {
+ result = append(result, *fill.Gradient)
+ }
+ }
+ require.Len(t, result, 1)
+ return result
+}
+
+func xlsxEntry(t *testing.T, buffer bytes.Buffer, name string) string {
+ t.Helper()
+ reader, err := zip.NewReader(bytes.NewReader(buffer.Bytes()), int64(buffer.Len()))
+ require.NoError(t, err)
+ for _, file := range reader.File {
+ if file.Name != name {
+ continue
+ }
+ entry, err := file.Open()
+ require.NoError(t, err)
+ data, readErr := io.ReadAll(entry)
+ require.NoError(t, readErr)
+ require.NoError(t, entry.Close())
+ return string(data)
+ }
+ t.Fatalf("XLSX archive did not contain %q", name)
+ return ""
+}
+
+func customNumberFormats(t *testing.T, buffer bytes.Buffer) []string {
+ t.Helper()
+ var styles struct {
+ NumFmts struct {
+ Formats []struct {
+ Code string `xml:"formatCode,attr"`
+ } `xml:"numFmt"`
+ } `xml:"numFmts"`
+ }
+ require.NoError(t, xml.Unmarshal([]byte(xlsxEntry(t, buffer, "xl/styles.xml")), &styles))
+ result := make([]string, 0, len(styles.NumFmts.Formats))
+ for _, format := range styles.NumFmts.Formats {
+ result = append(result, format.Code)
+ }
+ return result
+}
+
+func publicFieldNames(typ reflect.Type) []string {
+ result := make([]string, 0, typ.NumField())
+ for i := 0; i < typ.NumField(); i++ {
+ if typ.Field(i).IsExported() {
+ result = append(result, typ.Field(i).Name)
+ }
+ }
+ sort.Strings(result)
+ return result
+}
+
+func hasPublicField(typ reflect.Type, name string) bool {
+ _, ok := typ.FieldByName(name)
+ return ok
+}
+
+func containsString(values []string, want string) bool {
+ for _, value := range values {
+ if value == want {
+ return true
+ }
+ }
+ return false
+}
+
+func setPublicField(target any, name string, value any) bool {
+ field := reflect.ValueOf(target).Elem().FieldByName(name)
+ if !field.IsValid() || !field.CanSet() {
+ return false
+ }
+ valueRef := reflect.ValueOf(value)
+ if field.Kind() == reflect.Pointer && valueRef.Type().AssignableTo(field.Type().Elem()) {
+ pointer := reflect.New(field.Type().Elem())
+ pointer.Elem().Set(valueRef)
+ field.Set(pointer)
+ return true
+ }
+ if valueRef.Type().AssignableTo(field.Type()) {
+ field.Set(valueRef)
+ return true
+ }
+ if valueRef.Type().ConvertibleTo(field.Type()) {
+ field.Set(valueRef.Convert(field.Type()))
+ return true
+ }
+ return false
+}
+
+func publicFieldValue(target any, name string) any {
+ field := reflect.ValueOf(target).Elem().FieldByName(name)
+ if !field.IsValid() {
+ return nil
+ }
+ if field.Kind() == reflect.Pointer {
+ if field.IsNil() {
+ return nil
+ }
+ field = field.Elem()
+ }
+ return field.Interface()
+}
+
+func TestGetStyleDefinitionUsesTypedFields(t *testing.T) {
+ buffer := workbookWithStyle(t, &excelize.Style{Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#123456"}}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "bottom"}})
+ definition, err := GetStyleDefinition(buffer, "Sheet1", 1, 1)
+ require.NoError(t, err)
+ assert.Equal(t, excelizestyle.FillPatternSolid, definition.Fill.Pattern)
+ require.NotNil(t, definition.Alignment)
+ assert.Equal(t, excelizestyle.AlignmentVerticalBottom, definition.Alignment.Vertical)
+ expected, err := GetStyle(buffer, "Sheet1", 1, 1)
+ require.NoError(t, err)
+ assert.Equal(t, expected, definition.ToExcelize())
+ _, err = GetStyleDefinition(bytes.Buffer{}, "Sheet1", 1, 1)
+ require.Error(t, err)
+}
diff --git a/go.mod b/go.mod
index 5bec8e4..e1c1ae8 100644
--- a/go.mod
+++ b/go.mod
@@ -3,14 +3,17 @@ module github.com/tomtwinkle/excelizeam
go 1.25.0
require (
+ github.com/stretchr/testify v1.11.1
github.com/xuri/excelize/v2 v2.10.1
golang.org/x/sync v0.20.0
gotest.tools v2.2.0+incompatible
)
require (
+ github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/richardlehane/mscfb v1.0.6 // indirect
github.com/richardlehane/msoleps v1.0.6 // indirect
github.com/tiendc/go-deepcopy v1.7.2 // indirect
@@ -19,4 +22,5 @@ require (
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/net v0.51.0 // indirect
golang.org/x/text v0.34.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index 7b0aacd..de48c34 100644
--- a/go.sum
+++ b/go.sum
@@ -6,49 +6,32 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
-github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/mscfb v1.0.6 h1:eN3bvvZCp00bs7Zf52bxNwAx5lJDBK1tCuH19qq5aC8=
github.com/richardlehane/mscfb v1.0.6/go.mod h1:pe0+IUIc0AHh0+teNzBlJCtSyZdFOGgV4ZK9bsoV+Jo=
-github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
-github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
-github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/richardlehane/msoleps v1.0.6 h1:9BvkpjvD+iUBalUY4esMwv6uBkfOip/Lzvd93jvR9gg=
github.com/richardlehane/msoleps v1.0.6/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
-github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
-github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/tiendc/go-deepcopy v1.6.0 h1:0UtfV/imoCwlLxVsyfUd4hNHnB3drXsfle+wzSCA5Wo=
-github.com/tiendc/go-deepcopy v1.6.0/go.mod h1:toXoeQoUqXOOS/X4sKuiAoSk6elIdqc0pN7MTgOOo2I=
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tiendc/go-deepcopy v1.7.2 h1:Ut2yYR7W9tWjTQitganoIue4UGxZwCcJy3orjrrIj44=
github.com/tiendc/go-deepcopy v1.7.2/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ=
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
-github.com/xuri/excelize/v2 v2.9.1 h1:VdSGk+rraGmgLHGFaGG9/9IWu1nj4ufjJ7uwMDtj8Qw=
-github.com/xuri/excelize/v2 v2.9.1/go.mod h1:x7L6pKz2dvo9ejrRuD8Lnl98z4JLt0TGAwjhW+EiP8s=
github.com/xuri/excelize/v2 v2.10.1 h1:V62UlqopMqha3kOpnlHy2CcRVw1V8E63jFoWUmMzxN0=
github.com/xuri/excelize/v2 v2.10.1/go.mod h1:iG5tARpgaEeIhTqt3/fgXCGoBRt4hNXgCp3tfXKoOIc=
-github.com/xuri/nfp v0.0.1 h1:MDamSGatIvp8uOmDP8FnmjuQpu90NzdJxo7242ANR9Q=
-github.com/xuri/nfp v0.0.1/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE=
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
-golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
-golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
-golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
-golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
-golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
-golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
-golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
-golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=