styles.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. package excelize
  2. import (
  3. "encoding/json"
  4. "encoding/xml"
  5. "strconv"
  6. "strings"
  7. )
  8. // Excel styles can reference number formats that are built-in, all of which
  9. // have an id less than 164. This is a possibly incomplete list comprised of as
  10. // many of them as I could find.
  11. var builtInNumFmt = map[int]string{
  12. 0: "general",
  13. 1: "0",
  14. 2: "0.00",
  15. 3: "#,##0",
  16. 4: "#,##0.00",
  17. 9: "0%",
  18. 10: "0.00%",
  19. 11: "0.00e+00",
  20. 12: "# ?/?",
  21. 13: "# ??/??",
  22. 14: "mm-dd-yy",
  23. 15: "d-mmm-yy",
  24. 16: "d-mmm",
  25. 17: "mmm-yy",
  26. 18: "h:mm am/pm",
  27. 19: "h:mm:ss am/pm",
  28. 20: "h:mm",
  29. 21: "h:mm:ss",
  30. 22: "m/d/yy h:mm",
  31. 37: "#,##0 ;(#,##0)",
  32. 38: "#,##0 ;[red](#,##0)",
  33. 39: "#,##0.00;(#,##0.00)",
  34. 40: "#,##0.00;[red](#,##0.00)",
  35. 41: `_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)`,
  36. 42: `_("$"* #,##0_);_("$* \(#,##0\);_("$"* "-"_);_(@_)`,
  37. 43: `_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)`,
  38. 44: `_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)`,
  39. 45: "mm:ss",
  40. 46: "[h]:mm:ss",
  41. 47: "mmss.0",
  42. 48: "##0.0e+0",
  43. 49: "@",
  44. }
  45. // parseFormatStyleSet provides function to parse the format settings of the
  46. // borders.
  47. func parseFormatStyleSet(style string) (*formatCellStyle, error) {
  48. var format formatCellStyle
  49. err := json.Unmarshal([]byte(style), &format)
  50. return &format, err
  51. }
  52. // SetCellStyle provides function to set style for cells by given sheet index
  53. // and coordinate area in XLSX file. Note that the color field uses RGB color
  54. // code and diagonalDown and diagonalUp type border should be use same color in
  55. // the same coordinate area.
  56. //
  57. // For example create a borders of cell H9 on Sheet1:
  58. //
  59. // err := xlsx.SetCellStyle("Sheet1", "H9", "H9", `{"border":[{"type":"left","color":"0000FF","style":3},{"type":"top","color":"00FF00","style":4},{"type":"bottom","color":"FFFF00","style":5},{"type":"right","color":"FF0000","style":6},{"type":"diagonalDown","color":"A020F0","style":7},{"type":"diagonalUp","color":"A020F0","style":8}]}`)
  60. // if err != nil {
  61. // fmt.Println(err)
  62. // }
  63. //
  64. // Set gradient fill with vertical variants shading styles for cell H9 on
  65. // Sheet1:
  66. //
  67. // err := xlsx.SetCellStyle("Sheet1", "H9", "H9", `{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}}`)
  68. // if err != nil {
  69. // fmt.Println(err)
  70. // }
  71. //
  72. // Set solid style pattern fill for cell H9 on Sheet1:
  73. //
  74. // err := xlsx.SetCellStyle("Sheet1", "H9", "H9", `{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
  75. // if err != nil {
  76. // fmt.Println(err)
  77. // }
  78. //
  79. // Set alignment style for cell H9 on Sheet1:
  80. //
  81. // err = xlsx.SetCellStyle("Sheet1", "H9", "H9", `{"alignment":{"horizontal":"center","ident":1,"justify_last_line":true,"reading_order":0,"relative_indent":1,"shrink_to_fit":true,"text_rotation":45,"vertical":"","wrap_text":true}}`)
  82. // if err != nil {
  83. // fmt.Println(err)
  84. // }
  85. //
  86. // Dates and times in Excel are represented by real numbers, for example "Apr 7
  87. // 2017 12:00 PM" is represented by the number 42920.5. Set date and time format
  88. // for cell H9 on Sheet1:
  89. //
  90. // xlsx.SetCellValue("Sheet2", "H9", 42920.5)
  91. // err = xlsx.SetCellStyle("Sheet1", "H9", "H9", `{"number_format": 22}`)
  92. // if err != nil {
  93. // fmt.Println(err)
  94. // }
  95. //
  96. // Set font style for cell H9 on Sheet1:
  97. //
  98. // err = xlsx.SetCellStyle("Sheet1", "H9", "H9", `{"font":{"bold":true,"italic":true,"family":"Berlin Sans FB Demi","size":36,"color":"#777777"}}`)
  99. // if err != nil {
  100. // fmt.Println(err)
  101. // }
  102. //
  103. // The following shows the border styles sorted by excelize index number:
  104. //
  105. // +-------+---------------+--------+-----------------+
  106. // | Index | Name | Weight | Style |
  107. // +=======+===============+========+=================+
  108. // | 0 | None | 0 | |
  109. // +-------+---------------+--------+-----------------+
  110. // | 1 | Continuous | 1 | ``-----------`` |
  111. // +-------+---------------+--------+-----------------+
  112. // | 2 | Continuous | 2 | ``-----------`` |
  113. // +-------+---------------+--------+-----------------+
  114. // | 3 | Dash | 1 | ``- - - - - -`` |
  115. // +-------+---------------+--------+-----------------+
  116. // | 4 | Dot | 1 | ``. . . . . .`` |
  117. // +-------+---------------+--------+-----------------+
  118. // | 5 | Continuous | 3 | ``-----------`` |
  119. // +-------+---------------+--------+-----------------+
  120. // | 6 | Double | 3 | ``===========`` |
  121. // +-------+---------------+--------+-----------------+
  122. // | 7 | Continuous | 0 | ``-----------`` |
  123. // +-------+---------------+--------+-----------------+
  124. // | 8 | Dash | 2 | ``- - - - - -`` |
  125. // +-------+---------------+--------+-----------------+
  126. // | 9 | Dash Dot | 1 | ``- . - . - .`` |
  127. // +-------+---------------+--------+-----------------+
  128. // | 10 | Dash Dot | 2 | ``- . - . - .`` |
  129. // +-------+---------------+--------+-----------------+
  130. // | 11 | Dash Dot Dot | 1 | ``- . . - . .`` |
  131. // +-------+---------------+--------+-----------------+
  132. // | 12 | Dash Dot Dot | 2 | ``- . . - . .`` |
  133. // +-------+---------------+--------+-----------------+
  134. // | 13 | SlantDash Dot | 2 | ``/ - . / - .`` |
  135. // +-------+---------------+--------+-----------------+
  136. //
  137. // The following shows the borders in the order shown in the Excel dialog:
  138. //
  139. // +-------+-----------------+-------+-----------------+
  140. // | Index | Style | Index | Style |
  141. // +=======+=================+=======+=================+
  142. // | 0 | None | 12 | ``- . . - . .`` |
  143. // +-------+-----------------+-------+-----------------+
  144. // | 7 | ``-----------`` | 13 | ``/ - . / - .`` |
  145. // +-------+-----------------+-------+-----------------+
  146. // | 4 | ``. . . . . .`` | 10 | ``- . - . - .`` |
  147. // +-------+-----------------+-------+-----------------+
  148. // | 11 | ``- . . - . .`` | 8 | ``- - - - - -`` |
  149. // +-------+-----------------+-------+-----------------+
  150. // | 9 | ``- . - . - .`` | 2 | ``-----------`` |
  151. // +-------+-----------------+-------+-----------------+
  152. // | 3 | ``- - - - - -`` | 5 | ``-----------`` |
  153. // +-------+-----------------+-------+-----------------+
  154. // | 1 | ``-----------`` | 6 | ``===========`` |
  155. // +-------+-----------------+-------+-----------------+
  156. //
  157. // The following shows the shading styles sorted by excelize index number:
  158. //
  159. // +-------+-----------------+-------+-----------------+
  160. // | Index | Style | Index | Style |
  161. // +=======+=================+=======+=================+
  162. // | 0 | Horizontal | 3 | Diagonal down |
  163. // +-------+-----------------+-------+-----------------+
  164. // | 1 | Vertical | 4 | From corner |
  165. // +-------+-----------------+-------+-----------------+
  166. // | 2 | Diagonal Up | 5 | From center |
  167. // +-------+-----------------+-------+-----------------+
  168. //
  169. // The following shows the patterns styles sorted by excelize index number:
  170. //
  171. // +-------+-----------------+-------+-----------------+
  172. // | Index | Style | Index | Style |
  173. // +=======+=================+=======+=================+
  174. // | 0 | None | 10 | darkTrellis |
  175. // +-------+-----------------+-------+-----------------+
  176. // | 1 | solid | 11 | lightHorizontal |
  177. // +-------+-----------------+-------+-----------------+
  178. // | 2 | mediumGray | 12 | lightVertical |
  179. // +-------+-----------------+-------+-----------------+
  180. // | 3 | darkGray | 13 | lightDown |
  181. // +-------+-----------------+-------+-----------------+
  182. // | 4 | lightGray | 14 | lightUp |
  183. // +-------+-----------------+-------+-----------------+
  184. // | 5 | darkHorizontal | 15 | lightGrid |
  185. // +-------+-----------------+-------+-----------------+
  186. // | 6 | darkVertical | 16 | lightTrellis |
  187. // +-------+-----------------+-------+-----------------+
  188. // | 7 | darkDown | 17 | gray125 |
  189. // +-------+-----------------+-------+-----------------+
  190. // | 8 | darkUp | 18 | gray0625 |
  191. // +-------+-----------------+-------+-----------------+
  192. // | 9 | darkGrid | | |
  193. // +-------+-----------------+-------+-----------------+
  194. //
  195. // The following the type of horizontal alignment in cells:
  196. //
  197. // +------------------+
  198. // | Style |
  199. // +==================+
  200. // | left |
  201. // +------------------+
  202. // | center |
  203. // +------------------+
  204. // | right |
  205. // +------------------+
  206. // | fill |
  207. // +------------------+
  208. // | justify |
  209. // +------------------+
  210. // | centerContinuous |
  211. // +------------------+
  212. // | distributed |
  213. // +------------------+
  214. //
  215. // The following the type of vertical alignment in cells:
  216. //
  217. // +------------------+
  218. // | Style |
  219. // +==================+
  220. // | top |
  221. // +------------------+
  222. // | center |
  223. // +------------------+
  224. // | justify |
  225. // +------------------+
  226. // | distributed |
  227. // +------------------+
  228. //
  229. // The following the type of font underline style:
  230. //
  231. // +------------------+
  232. // | Style |
  233. // +==================+
  234. // | single |
  235. // +------------------+
  236. // | double |
  237. // +------------------+
  238. //
  239. // Excel's built-in formats are shown in the following table:
  240. //
  241. // +-------+----------------------------------------------------+
  242. // | Index | Format String |
  243. // +=======+====================================================+
  244. // | 0 | General |
  245. // +-------+----------------------------------------------------+
  246. // | 1 | 0 |
  247. // +-------+----------------------------------------------------+
  248. // | 2 | 0.00 |
  249. // +-------+----------------------------------------------------+
  250. // | 3 | #,##0 |
  251. // +-------+----------------------------------------------------+
  252. // | 4 | #,##0.00 |
  253. // +-------+----------------------------------------------------+
  254. // | 5 | ($#,##0_);($#,##0) |
  255. // +-------+----------------------------------------------------+
  256. // | 6 | ($#,##0_);[Red]($#,##0) |
  257. // +-------+----------------------------------------------------+
  258. // | 7 | ($#,##0.00_);($#,##0.00) |
  259. // +-------+----------------------------------------------------+
  260. // | 8 | ($#,##0.00_);[Red]($#,##0.00) |
  261. // +-------+----------------------------------------------------+
  262. // | 9 | 0% |
  263. // +-------+----------------------------------------------------+
  264. // | 10 | 0.00% |
  265. // +-------+----------------------------------------------------+
  266. // | 11 | 0.00E+00 |
  267. // +-------+----------------------------------------------------+
  268. // | 12 | # ?/? |
  269. // +-------+----------------------------------------------------+
  270. // | 13 | # ??/?? |
  271. // +-------+----------------------------------------------------+
  272. // | 14 | m/d/yy |
  273. // +-------+----------------------------------------------------+
  274. // | 15 | d-mmm-yy |
  275. // +-------+----------------------------------------------------+
  276. // | 16 | d-mmm |
  277. // +-------+----------------------------------------------------+
  278. // | 17 | mmm-yy |
  279. // +-------+----------------------------------------------------+
  280. // | 18 | h:mm AM/PM |
  281. // +-------+----------------------------------------------------+
  282. // | 19 | h:mm:ss AM/PM |
  283. // +-------+----------------------------------------------------+
  284. // | 20 | h:mm |
  285. // +-------+----------------------------------------------------+
  286. // | 21 | h:mm:ss |
  287. // +-------+----------------------------------------------------+
  288. // | 22 | m/d/yy h:mm |
  289. // +-------+----------------------------------------------------+
  290. // | ... | ... |
  291. // +-------+----------------------------------------------------+
  292. // | 37 | (#,##0_);(#,##0) |
  293. // +-------+----------------------------------------------------+
  294. // | 38 | (#,##0_);[Red](#,##0) |
  295. // +-------+----------------------------------------------------+
  296. // | 39 | (#,##0.00_);(#,##0.00) |
  297. // +-------+----------------------------------------------------+
  298. // | 40 | (#,##0.00_);[Red](#,##0.00) |
  299. // +-------+----------------------------------------------------+
  300. // | 41 | _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_) |
  301. // +-------+----------------------------------------------------+
  302. // | 42 | _($* #,##0_);_($* (#,##0);_($* "-"_);_(@_) |
  303. // +-------+----------------------------------------------------+
  304. // | 43 | _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_) |
  305. // +-------+----------------------------------------------------+
  306. // | 44 | _($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_) |
  307. // +-------+----------------------------------------------------+
  308. // | 45 | mm:ss |
  309. // +-------+----------------------------------------------------+
  310. // | 46 | [h]:mm:ss |
  311. // +-------+----------------------------------------------------+
  312. // | 47 | mm:ss.0 |
  313. // +-------+----------------------------------------------------+
  314. // | 48 | ##0.0E+0 |
  315. // +-------+----------------------------------------------------+
  316. // | 49 | @ |
  317. // +-------+----------------------------------------------------+
  318. //
  319. func (f *File) SetCellStyle(sheet, hcell, vcell, style string) error {
  320. var styleSheet xlsxStyleSheet
  321. xml.Unmarshal([]byte(f.readXML("xl/styles.xml")), &styleSheet)
  322. formatCellStyle, err := parseFormatStyleSet(style)
  323. if err != nil {
  324. return err
  325. }
  326. numFmtID := setNumFmt(&styleSheet, formatCellStyle)
  327. fontID := setFont(&styleSheet, formatCellStyle)
  328. borderID := setBorders(&styleSheet, formatCellStyle)
  329. fillID := setFills(&styleSheet, formatCellStyle)
  330. applyAlignment, alignment := setAlignment(&styleSheet, formatCellStyle)
  331. cellXfsID := setCellXfs(&styleSheet, fontID, numFmtID, fillID, borderID, applyAlignment, alignment)
  332. output, err := xml.Marshal(styleSheet)
  333. if err != nil {
  334. return err
  335. }
  336. f.saveFileList("xl/styles.xml", replaceWorkSheetsRelationshipsNameSpace(string(output)))
  337. f.setCellStyle(sheet, hcell, vcell, cellXfsID)
  338. return err
  339. }
  340. // setFont provides function to add font style by given cell format settings.
  341. func setFont(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
  342. if formatCellStyle.Font == nil {
  343. return 0
  344. }
  345. fontUnderlineType := map[string]string{"single": "single", "double": "double"}
  346. if formatCellStyle.Font.Family == "" {
  347. formatCellStyle.Font.Family = "Calibri"
  348. }
  349. if formatCellStyle.Font.Size < 1 {
  350. formatCellStyle.Font.Size = 11
  351. }
  352. if formatCellStyle.Font.Color == "" {
  353. formatCellStyle.Font.Color = "#000000"
  354. }
  355. f := font{
  356. B: formatCellStyle.Font.Bold,
  357. I: formatCellStyle.Font.Italic,
  358. Sz: &attrValInt{Val: formatCellStyle.Font.Size},
  359. Color: &xlsxColor{RGB: getPaletteColor(formatCellStyle.Font.Color)},
  360. Name: &attrValString{Val: formatCellStyle.Font.Family},
  361. Family: &attrValInt{Val: 2},
  362. Scheme: &attrValString{Val: "minor"},
  363. }
  364. val, ok := fontUnderlineType[formatCellStyle.Font.Underline]
  365. if ok {
  366. f.U = &attrValString{Val: val}
  367. }
  368. font, _ := xml.Marshal(f)
  369. style.Fonts.Count++
  370. style.Fonts.Font = append(style.Fonts.Font, &xlsxFont{
  371. Font: string(font[6 : len(font)-7]),
  372. })
  373. return style.Fonts.Count - 1
  374. }
  375. // setNumFmt provides function to check if number format code in the range of
  376. // built-in values.
  377. func setNumFmt(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
  378. _, ok := builtInNumFmt[formatCellStyle.NumFmt]
  379. if !ok {
  380. return 0
  381. }
  382. return formatCellStyle.NumFmt
  383. }
  384. // setFills provides function to add fill elements in the styles.xml by given
  385. // cell format settings.
  386. func setFills(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
  387. var patterns = []string{
  388. "none",
  389. "solid",
  390. "mediumGray",
  391. "darkGray",
  392. "lightGray",
  393. "darkHorizontal",
  394. "darkVertical",
  395. "darkDown",
  396. "darkUp",
  397. "darkGrid",
  398. "darkTrellis",
  399. "lightHorizontal",
  400. "lightVertical",
  401. "lightDown",
  402. "lightUp",
  403. "lightGrid",
  404. "lightTrellis",
  405. "gray125",
  406. "gray0625",
  407. }
  408. var variants = []float64{
  409. 90,
  410. 0,
  411. 45,
  412. 135,
  413. }
  414. var fill xlsxFill
  415. switch formatCellStyle.Fill.Type {
  416. case "gradient":
  417. if len(formatCellStyle.Fill.Color) != 2 {
  418. break
  419. }
  420. var gradient xlsxGradientFill
  421. switch formatCellStyle.Fill.Shading {
  422. case 0, 1, 2, 3:
  423. gradient.Degree = variants[formatCellStyle.Fill.Shading]
  424. case 4:
  425. gradient.Type = "path"
  426. case 5:
  427. gradient.Type = "path"
  428. gradient.Bottom = 0.5
  429. gradient.Left = 0.5
  430. gradient.Right = 0.5
  431. gradient.Top = 0.5
  432. default:
  433. break
  434. }
  435. var stops []*xlsxGradientFillStop
  436. for index, color := range formatCellStyle.Fill.Color {
  437. var stop xlsxGradientFillStop
  438. stop.Position = float64(index)
  439. stop.Color.RGB = getPaletteColor(color)
  440. stops = append(stops, &stop)
  441. }
  442. gradient.Stop = stops
  443. fill.GradientFill = &gradient
  444. case "pattern":
  445. if formatCellStyle.Fill.Pattern > 18 || formatCellStyle.Fill.Pattern < 0 {
  446. break
  447. }
  448. if len(formatCellStyle.Fill.Color) < 1 {
  449. break
  450. }
  451. var pattern xlsxPatternFill
  452. pattern.PatternType = patterns[formatCellStyle.Fill.Pattern]
  453. pattern.FgColor.RGB = getPaletteColor(formatCellStyle.Fill.Color[0])
  454. fill.PatternFill = &pattern
  455. }
  456. style.Fills.Count++
  457. style.Fills.Fill = append(style.Fills.Fill, &fill)
  458. return style.Fills.Count - 1
  459. }
  460. // setAlignment provides function to formatting information pertaining to text
  461. // alignment in cells. There are a variety of choices for how text is aligned
  462. // both horizontally and vertically, as well as indentation settings, and so on.
  463. func setAlignment(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) (bool, *xlsxAlignment) {
  464. if formatCellStyle.Alignment == nil {
  465. return false, &xlsxAlignment{}
  466. }
  467. var alignment = xlsxAlignment{
  468. Horizontal: formatCellStyle.Alignment.Horizontal,
  469. Indent: formatCellStyle.Alignment.Indent,
  470. JustifyLastLine: formatCellStyle.Alignment.JustifyLastLine,
  471. ReadingOrder: formatCellStyle.Alignment.ReadingOrder,
  472. RelativeIndent: formatCellStyle.Alignment.RelativeIndent,
  473. ShrinkToFit: formatCellStyle.Alignment.ShrinkToFit,
  474. TextRotation: formatCellStyle.Alignment.TextRotation,
  475. Vertical: formatCellStyle.Alignment.Vertical,
  476. WrapText: formatCellStyle.Alignment.WrapText,
  477. }
  478. return true, &alignment
  479. }
  480. // setBorders provides function to add border elements in the styles.xml by
  481. // given borders format settings.
  482. func setBorders(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
  483. var styles = []string{
  484. "none",
  485. "thin",
  486. "medium",
  487. "dashed",
  488. "dotted",
  489. "thick",
  490. "double",
  491. "hair",
  492. "mediumDashed",
  493. "dashDot",
  494. "mediumDashDot",
  495. "dashDotDot",
  496. "mediumDashDotDot",
  497. "slantDashDot",
  498. }
  499. var border xlsxBorder
  500. for _, v := range formatCellStyle.Border {
  501. if v.Style > 13 || v.Style < 0 {
  502. continue
  503. }
  504. var color xlsxColor
  505. color.RGB = getPaletteColor(v.Color)
  506. switch v.Type {
  507. case "left":
  508. border.Left.Style = styles[v.Style]
  509. border.Left.Color = &color
  510. case "right":
  511. border.Right.Style = styles[v.Style]
  512. border.Right.Color = &color
  513. case "top":
  514. border.Top.Style = styles[v.Style]
  515. border.Top.Color = &color
  516. case "bottom":
  517. border.Bottom.Style = styles[v.Style]
  518. border.Bottom.Color = &color
  519. case "diagonalUp":
  520. border.Diagonal.Style = styles[v.Style]
  521. border.Diagonal.Color = &color
  522. border.DiagonalUp = true
  523. case "diagonalDown":
  524. border.Diagonal.Style = styles[v.Style]
  525. border.Diagonal.Color = &color
  526. border.DiagonalDown = true
  527. }
  528. }
  529. style.Borders.Count++
  530. style.Borders.Border = append(style.Borders.Border, &border)
  531. return style.Borders.Count - 1
  532. }
  533. // setCellXfs provides function to set describes all of the formatting for a
  534. // cell.
  535. func setCellXfs(style *xlsxStyleSheet, fontID, numFmtID, fillID, borderID int, applyAlignment bool, alignment *xlsxAlignment) int {
  536. var xf xlsxXf
  537. xf.FontID = fontID
  538. if fontID != 0 {
  539. xf.ApplyFont = true
  540. }
  541. xf.NumFmtID = numFmtID
  542. if numFmtID != 0 {
  543. xf.ApplyNumberFormat = true
  544. }
  545. xf.FillID = fillID
  546. xf.BorderID = borderID
  547. style.CellXfs.Count++
  548. xf.Alignment = alignment
  549. xf.ApplyAlignment = applyAlignment
  550. style.CellXfs.Xf = append(style.CellXfs.Xf, xf)
  551. return style.CellXfs.Count - 1
  552. }
  553. // setCellStyle provides function to add style attribute for cells by given
  554. // sheet index, coordinate area and style ID.
  555. func (f *File) setCellStyle(sheet, hcell, vcell string, styleID int) {
  556. hcell = strings.ToUpper(hcell)
  557. vcell = strings.ToUpper(vcell)
  558. // Coordinate conversion, convert C1:B3 to 2,0,1,2.
  559. hcol := string(strings.Map(letterOnlyMapF, hcell))
  560. hrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, hcell))
  561. hyAxis := hrow - 1
  562. hxAxis := titleToNumber(hcol)
  563. vcol := string(strings.Map(letterOnlyMapF, vcell))
  564. vrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, vcell))
  565. vyAxis := vrow - 1
  566. vxAxis := titleToNumber(vcol)
  567. if vxAxis < hxAxis {
  568. hcell, vcell = vcell, hcell
  569. vxAxis, hxAxis = hxAxis, vxAxis
  570. }
  571. if vyAxis < hyAxis {
  572. hcell, vcell = vcell, hcell
  573. vyAxis, hyAxis = hyAxis, vyAxis
  574. }
  575. // Correct the coordinate area, such correct C1:B3 to B1:C3.
  576. hcell = toAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1)
  577. vcell = toAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
  578. xlsx := f.workSheetReader(sheet)
  579. completeRow(xlsx, vxAxis+1, vyAxis+1)
  580. completeCol(xlsx, vxAxis+1, vyAxis+1)
  581. for r, row := range xlsx.SheetData.Row {
  582. for k, c := range row.C {
  583. if checkCellInArea(c.R, hcell+":"+vcell) {
  584. xlsx.SheetData.Row[r].C[k].S = styleID
  585. }
  586. }
  587. }
  588. }
  589. // getPaletteColor provides function to convert the RBG color by given string.
  590. func getPaletteColor(color string) string {
  591. return "FF" + strings.Replace(strings.ToUpper(color), "#", "", -1)
  592. }