@@ -1032,6 +1032,303 @@ func (f *File) NewStyle(style *Style) (int, error) {
10321032 return setCellXfs (s , fontID , numFmtID , fillID , borderID , applyAlignment , applyProtection , alignment , protection )
10331033}
10341034
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+
10351332// getXfIDFuncs provides a function to get xfID by given style.
10361333var getXfIDFuncs = map [string ]func (int , xlsxXf , * Style ) bool {
10371334 "numFmt" : func (numFmtID int , xf xlsxXf , style * Style ) bool {
@@ -1406,9 +1703,15 @@ func getCustomNumFmtID(styleSheet *xlsxStyleSheet, style *Style) (customNumFmtID
14061703 return
14071704}
14081705
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+
14091712// setLangNumFmt provides a function to set number format code with language.
14101713func setLangNumFmt (style * Style ) int {
1411- if ( 27 <= style .NumFmt && style . NumFmt <= 36 ) || ( 50 <= style . NumFmt && style . NumFmt <= 81 ) {
1714+ if isLangNumFmt ( style .NumFmt ) {
14121715 return style .NumFmt
14131716 }
14141717 return 0
0 commit comments