@@ -1032,6 +1032,303 @@ func (f *File) NewStyle(style *Style) (int, error) {
1032
1032
return setCellXfs (s , fontID , numFmtID , fillID , borderID , applyAlignment , applyProtection , alignment , protection )
1033
1033
}
1034
1034
1035
+ var (
1036
+ // styleBorders list all types of the cell border style.
1037
+ styleBorders = []string {
1038
+ "none" ,
1039
+ "thin" ,
1040
+ "medium" ,
1041
+ "dashed" ,
1042
+ "dotted" ,
1043
+ "thick" ,
1044
+ "double" ,
1045
+ "hair" ,
1046
+ "mediumDashed" ,
1047
+ "dashDot" ,
1048
+ "mediumDashDot" ,
1049
+ "dashDotDot" ,
1050
+ "mediumDashDotDot" ,
1051
+ "slantDashDot" ,
1052
+ }
1053
+ // styleBorderTypes list all types of the cell border.
1054
+ styleBorderTypes = []string {
1055
+ "left" , "right" , "top" , "bottom" , "diagonalUp" , "diagonalDown" ,
1056
+ }
1057
+ // styleFillPatterns list all types of the cell fill style.
1058
+ styleFillPatterns = []string {
1059
+ "none" ,
1060
+ "solid" ,
1061
+ "mediumGray" ,
1062
+ "darkGray" ,
1063
+ "lightGray" ,
1064
+ "darkHorizontal" ,
1065
+ "darkVertical" ,
1066
+ "darkDown" ,
1067
+ "darkUp" ,
1068
+ "darkGrid" ,
1069
+ "darkTrellis" ,
1070
+ "lightHorizontal" ,
1071
+ "lightVertical" ,
1072
+ "lightDown" ,
1073
+ "lightUp" ,
1074
+ "lightGrid" ,
1075
+ "lightTrellis" ,
1076
+ "gray125" ,
1077
+ "gray0625" ,
1078
+ }
1079
+ // styleFillVariants list all preset variants of the fill style.
1080
+ styleFillVariants = []xlsxGradientFill {
1081
+ {Degree : 90 , Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}},
1082
+ {Degree : 270 , Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}},
1083
+ {Degree : 90 , Stop : []* xlsxGradientFillStop {{}, {Position : 0.5 }, {Position : 1 }}},
1084
+ {Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}},
1085
+ {Degree : 180 , Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}},
1086
+ {Stop : []* xlsxGradientFillStop {{}, {Position : 0.5 }, {Position : 1 }}},
1087
+ {Degree : 45 , Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}},
1088
+ {Degree : 255 , Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}},
1089
+ {Degree : 45 , Stop : []* xlsxGradientFillStop {{}, {Position : 0.5 }, {Position : 1 }}},
1090
+ {Degree : 135 , Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}},
1091
+ {Degree : 315 , Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}},
1092
+ {Degree : 135 , Stop : []* xlsxGradientFillStop {{}, {Position : 0.5 }, {Position : 1 }}},
1093
+ {Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}, Type : "path" },
1094
+ {Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}, Type : "path" , Left : 1 , Right : 1 },
1095
+ {Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}, Type : "path" , Bottom : 1 , Top : 1 },
1096
+ {Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}, Type : "path" , Bottom : 1 , Left : 1 , Right : 1 , Top : 1 },
1097
+ {Stop : []* xlsxGradientFillStop {{}, {Position : 1 }}, Type : "path" , Bottom : 0.5 , Left : 0.5 , Right : 0.5 , Top : 0.5 },
1098
+ }
1099
+ )
1100
+
1101
+ // getThemeColor provides a function to convert theme color or index color to
1102
+ // RGB color.
1103
+ func (f * File ) getThemeColor (clr * xlsxColor ) string {
1104
+ var RGB string
1105
+ if clr == nil || f .Theme == nil {
1106
+ return RGB
1107
+ }
1108
+ if clrScheme := f .Theme .ThemeElements .ClrScheme ; clr .Theme != nil {
1109
+ if val , ok := map [int ]* string {
1110
+ 0 : & clrScheme .Lt1 .SysClr .LastClr ,
1111
+ 1 : & clrScheme .Dk1 .SysClr .LastClr ,
1112
+ 2 : clrScheme .Lt2 .SrgbClr .Val ,
1113
+ 3 : clrScheme .Dk2 .SrgbClr .Val ,
1114
+ 4 : clrScheme .Accent1 .SrgbClr .Val ,
1115
+ 5 : clrScheme .Accent2 .SrgbClr .Val ,
1116
+ 6 : clrScheme .Accent3 .SrgbClr .Val ,
1117
+ 7 : clrScheme .Accent4 .SrgbClr .Val ,
1118
+ 8 : clrScheme .Accent5 .SrgbClr .Val ,
1119
+ 9 : clrScheme .Accent6 .SrgbClr .Val ,
1120
+ }[* clr .Theme ]; ok && val != nil {
1121
+ return strings .TrimPrefix (ThemeColor (* val , clr .Tint ), "FF" )
1122
+ }
1123
+ }
1124
+ if len (clr .RGB ) == 6 {
1125
+ return clr .RGB
1126
+ }
1127
+ if len (clr .RGB ) == 8 {
1128
+ return strings .TrimPrefix (clr .RGB , "FF" )
1129
+ }
1130
+ if f .Styles .Colors != nil && clr .Indexed < len (f .Styles .Colors .IndexedColors .RgbColor ) {
1131
+ return strings .TrimPrefix (ThemeColor (strings .TrimPrefix (f .Styles .Colors .IndexedColors .RgbColor [clr .Indexed ].RGB , "FF" ), clr .Tint ), "FF" )
1132
+ }
1133
+ if clr .Indexed < len (IndexedColorMapping ) {
1134
+ return strings .TrimPrefix (ThemeColor (IndexedColorMapping [clr .Indexed ], clr .Tint ), "FF" )
1135
+ }
1136
+ return RGB
1137
+ }
1138
+
1139
+ // extractBorders provides a function to extract borders styles settings by
1140
+ // given border styles definition.
1141
+ func (f * File ) extractBorders (xf xlsxXf , s * xlsxStyleSheet , style * Style ) {
1142
+ if xf .ApplyBorder != nil && * xf .ApplyBorder &&
1143
+ xf .BorderID != nil && s .Borders != nil &&
1144
+ * xf .BorderID < len (s .Borders .Border ) {
1145
+ if bdr := s .Borders .Border [* xf .BorderID ]; bdr != nil {
1146
+
1147
+ var borders []Border
1148
+ extractBorder := func (lineType string , line xlsxLine ) {
1149
+ if line .Style != "" {
1150
+ borders = append (borders , Border {
1151
+ Type : lineType ,
1152
+ Color : f .getThemeColor (line .Color ),
1153
+ Style : inStrSlice (styleBorders , line .Style , false ),
1154
+ })
1155
+ }
1156
+ }
1157
+ for i , line := range []xlsxLine {
1158
+ bdr .Left , bdr .Right , bdr .Top , bdr .Bottom , bdr .Diagonal , bdr .Diagonal ,
1159
+ } {
1160
+ if i < 4 {
1161
+ extractBorder (styleBorderTypes [i ], line )
1162
+ }
1163
+ if i == 4 && bdr .DiagonalUp {
1164
+ extractBorder (styleBorderTypes [i ], line )
1165
+ }
1166
+ if i == 5 && bdr .DiagonalDown {
1167
+ extractBorder (styleBorderTypes [i ], line )
1168
+ }
1169
+ }
1170
+ style .Border = borders
1171
+ }
1172
+ }
1173
+ }
1174
+
1175
+ // extractFills provides a function to extract fill styles settings by
1176
+ // given fill styles definition.
1177
+ func (f * File ) extractFills (xf xlsxXf , s * xlsxStyleSheet , style * Style ) {
1178
+ if fl := s .Fills .Fill [* xf .FillID ]; fl != nil {
1179
+ var fill Fill
1180
+ if fl .GradientFill != nil {
1181
+ fill .Type = "gradient"
1182
+ for shading , variants := range styleFillVariants {
1183
+ if fl .GradientFill .Bottom == variants .Bottom &&
1184
+ fl .GradientFill .Degree == variants .Degree &&
1185
+ fl .GradientFill .Left == variants .Left &&
1186
+ fl .GradientFill .Right == variants .Right &&
1187
+ fl .GradientFill .Top == variants .Top &&
1188
+ fl .GradientFill .Type == variants .Type {
1189
+ fill .Shading = shading
1190
+ break
1191
+ }
1192
+ }
1193
+ for _ , stop := range fl .GradientFill .Stop {
1194
+ fill .Color = append (fill .Color , f .getThemeColor (& stop .Color ))
1195
+ }
1196
+ }
1197
+ if fl .PatternFill != nil {
1198
+ fill .Type = "pattern"
1199
+ fill .Pattern = inStrSlice (styleFillPatterns , fl .PatternFill .PatternType , false )
1200
+ if fl .PatternFill .FgColor != nil {
1201
+ fill .Color = []string {f .getThemeColor (fl .PatternFill .FgColor )}
1202
+ }
1203
+ }
1204
+ style .Fill = fill
1205
+ }
1206
+ }
1207
+
1208
+ // extractFont provides a function to extract font styles settings by given
1209
+ // font styles definition.
1210
+ func (f * File ) extractFont (xf xlsxXf , s * xlsxStyleSheet , style * Style ) {
1211
+ if xf .ApplyFont != nil && * xf .ApplyFont &&
1212
+ xf .FontID != nil && s .Fonts != nil &&
1213
+ * xf .FontID < len (s .Fonts .Font ) {
1214
+ if fnt := s .Fonts .Font [* xf .FontID ]; fnt != nil {
1215
+ var font Font
1216
+ if fnt .B != nil {
1217
+ font .Bold = fnt .B .Value ()
1218
+ }
1219
+ if fnt .I != nil {
1220
+ font .Italic = fnt .I .Value ()
1221
+ }
1222
+ if fnt .U != nil {
1223
+ font .Underline = fnt .U .Value ()
1224
+ }
1225
+ if fnt .Name != nil {
1226
+ font .Family = fnt .Name .Value ()
1227
+ }
1228
+ if fnt .Sz != nil {
1229
+ font .Size = fnt .Sz .Value ()
1230
+ }
1231
+ if fnt .Strike != nil {
1232
+ font .Strike = fnt .Strike .Value ()
1233
+ }
1234
+ if fnt .Color != nil {
1235
+ font .Color = strings .TrimPrefix (fnt .Color .RGB , "FF" )
1236
+ font .ColorIndexed = fnt .Color .Indexed
1237
+ font .ColorTheme = fnt .Color .Theme
1238
+ font .ColorTint = fnt .Color .Tint
1239
+ }
1240
+ style .Font = & font
1241
+ }
1242
+ }
1243
+ }
1244
+
1245
+ // extractNumFmt provides a function to extract number format by given styles
1246
+ // definition.
1247
+ func (f * File ) extractNumFmt (xf xlsxXf , s * xlsxStyleSheet , style * Style ) {
1248
+ if xf .NumFmtID != nil {
1249
+ numFmtID := * xf .NumFmtID
1250
+ if _ , ok := builtInNumFmt [numFmtID ]; ok || isLangNumFmt (numFmtID ) {
1251
+ style .NumFmt = numFmtID
1252
+ return
1253
+ }
1254
+ if s .NumFmts != nil {
1255
+ for _ , numFmt := range s .NumFmts .NumFmt {
1256
+ style .CustomNumFmt = & numFmt .FormatCode
1257
+ if strings .Contains (numFmt .FormatCode , ";[Red]" ) {
1258
+ style .NegRed = true
1259
+ }
1260
+ for numFmtID , fmtCode := range currencyNumFmt {
1261
+ if style .NegRed {
1262
+ fmtCode += ";[Red]" + fmtCode
1263
+ }
1264
+ if numFmt .FormatCode == fmtCode {
1265
+ style .NumFmt = numFmtID
1266
+ }
1267
+ }
1268
+ }
1269
+ }
1270
+ }
1271
+ }
1272
+
1273
+ // extractAlignment provides a function to extract alignment format by
1274
+ // given style definition.
1275
+ func (f * File ) extractAlignment (xf xlsxXf , s * xlsxStyleSheet , style * Style ) {
1276
+ if xf .ApplyAlignment != nil && * xf .ApplyAlignment && xf .Alignment != nil {
1277
+ style .Alignment = & Alignment {
1278
+ Horizontal : xf .Alignment .Horizontal ,
1279
+ Indent : xf .Alignment .Indent ,
1280
+ JustifyLastLine : xf .Alignment .JustifyLastLine ,
1281
+ ReadingOrder : xf .Alignment .ReadingOrder ,
1282
+ RelativeIndent : xf .Alignment .RelativeIndent ,
1283
+ ShrinkToFit : xf .Alignment .ShrinkToFit ,
1284
+ TextRotation : xf .Alignment .TextRotation ,
1285
+ Vertical : xf .Alignment .Vertical ,
1286
+ WrapText : xf .Alignment .WrapText ,
1287
+ }
1288
+ }
1289
+ }
1290
+
1291
+ // extractProtection provides a function to extract protection settings by
1292
+ // given format definition.
1293
+ func (f * File ) extractProtection (xf xlsxXf , s * xlsxStyleSheet , style * Style ) {
1294
+ if xf .ApplyProtection != nil && * xf .ApplyProtection && xf .Protection != nil {
1295
+ style .Protection = & Protection {}
1296
+ if xf .Protection .Hidden != nil {
1297
+ style .Protection .Hidden = * xf .Protection .Hidden
1298
+ }
1299
+ if xf .Protection .Locked != nil {
1300
+ style .Protection .Locked = * xf .Protection .Locked
1301
+ }
1302
+ }
1303
+ }
1304
+
1305
+ // GetStyle get style details by given style index.
1306
+ func (f * File ) GetStyle (idx int ) (* Style , error ) {
1307
+ var style * Style
1308
+ f .mu .Lock ()
1309
+ s , err := f .stylesReader ()
1310
+ if err != nil {
1311
+ return style , err
1312
+ }
1313
+ f .mu .Unlock ()
1314
+ if idx < 0 || s .CellXfs == nil || len (s .CellXfs .Xf ) <= idx {
1315
+ return style , newInvalidStyleID (idx )
1316
+ }
1317
+ style = & Style {}
1318
+ xf := s .CellXfs .Xf [idx ]
1319
+ if xf .ApplyFill != nil && * xf .ApplyFill &&
1320
+ xf .FillID != nil && s .Fills != nil &&
1321
+ * xf .FillID < len (s .Fills .Fill ) {
1322
+ f .extractFills (xf , s , style )
1323
+ }
1324
+ f .extractBorders (xf , s , style )
1325
+ f .extractFont (xf , s , style )
1326
+ f .extractAlignment (xf , s , style )
1327
+ f .extractProtection (xf , s , style )
1328
+ f .extractNumFmt (xf , s , style )
1329
+ return style , nil
1330
+ }
1331
+
1035
1332
// getXfIDFuncs provides a function to get xfID by given style.
1036
1333
var getXfIDFuncs = map [string ]func (int , xlsxXf , * Style ) bool {
1037
1334
"numFmt" : func (numFmtID int , xf xlsxXf , style * Style ) bool {
@@ -1406,9 +1703,15 @@ func getCustomNumFmtID(styleSheet *xlsxStyleSheet, style *Style) (customNumFmtID
1406
1703
return
1407
1704
}
1408
1705
1706
+ // isLangNumFmt provides a function to returns if a given number format ID is a
1707
+ // built-in language glyphs number format code.
1708
+ func isLangNumFmt (ID int ) bool {
1709
+ return (27 <= ID && ID <= 36 ) || (50 <= ID && ID <= 62 ) || (67 <= ID && ID <= 81 )
1710
+ }
1711
+
1409
1712
// setLangNumFmt provides a function to set number format code with language.
1410
1713
func setLangNumFmt (style * Style ) int {
1411
- if ( 27 <= style .NumFmt && style . NumFmt <= 36 ) || ( 50 <= style . NumFmt && style . NumFmt <= 81 ) {
1714
+ if isLangNumFmt ( style .NumFmt ) {
1412
1715
return style .NumFmt
1413
1716
}
1414
1717
return 0
0 commit comments