sparkline.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. // Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
  2. // this source code is governed by a BSD-style license that can be found in
  3. // the LICENSE file.
  4. //
  5. // Package excelize providing a set of functions that allow you to write to and
  6. // read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
  7. // writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
  8. // Supports complex components by high compatibility, and provided streaming
  9. // API for generating or reading data from a worksheet with huge amounts of
  10. // data. This library needs Go version 1.16 or later.
  11. package excelize
  12. import (
  13. "encoding/xml"
  14. "io"
  15. "sort"
  16. "strings"
  17. )
  18. // addSparklineGroupByStyle provides a function to create x14:sparklineGroups
  19. // element by given sparkline style ID.
  20. func (f *File) addSparklineGroupByStyle(ID int) *xlsxX14SparklineGroup {
  21. groups := []*xlsxX14SparklineGroup{
  22. {
  23. ColorSeries: &xlsxTabColor{Theme: 4, Tint: -0.499984740745262},
  24. ColorNegative: &xlsxTabColor{Theme: 5},
  25. ColorMarkers: &xlsxTabColor{Theme: 4, Tint: -0.499984740745262},
  26. ColorFirst: &xlsxTabColor{Theme: 4, Tint: 0.39997558519241921},
  27. ColorLast: &xlsxTabColor{Theme: 4, Tint: 0.39997558519241921},
  28. ColorHigh: &xlsxTabColor{Theme: 4},
  29. ColorLow: &xlsxTabColor{Theme: 4},
  30. }, // 0
  31. {
  32. ColorSeries: &xlsxTabColor{Theme: 4, Tint: -0.499984740745262},
  33. ColorNegative: &xlsxTabColor{Theme: 5},
  34. ColorMarkers: &xlsxTabColor{Theme: 4, Tint: -0.499984740745262},
  35. ColorFirst: &xlsxTabColor{Theme: 4, Tint: 0.39997558519241921},
  36. ColorLast: &xlsxTabColor{Theme: 4, Tint: 0.39997558519241921},
  37. ColorHigh: &xlsxTabColor{Theme: 4},
  38. ColorLow: &xlsxTabColor{Theme: 4},
  39. }, // 1
  40. {
  41. ColorSeries: &xlsxTabColor{Theme: 5, Tint: -0.499984740745262},
  42. ColorNegative: &xlsxTabColor{Theme: 6},
  43. ColorMarkers: &xlsxTabColor{Theme: 5, Tint: -0.499984740745262},
  44. ColorFirst: &xlsxTabColor{Theme: 5, Tint: 0.39997558519241921},
  45. ColorLast: &xlsxTabColor{Theme: 5, Tint: 0.39997558519241921},
  46. ColorHigh: &xlsxTabColor{Theme: 5},
  47. ColorLow: &xlsxTabColor{Theme: 5},
  48. }, // 2
  49. {
  50. ColorSeries: &xlsxTabColor{Theme: 6, Tint: -0.499984740745262},
  51. ColorNegative: &xlsxTabColor{Theme: 7},
  52. ColorMarkers: &xlsxTabColor{Theme: 6, Tint: -0.499984740745262},
  53. ColorFirst: &xlsxTabColor{Theme: 6, Tint: 0.39997558519241921},
  54. ColorLast: &xlsxTabColor{Theme: 6, Tint: 0.39997558519241921},
  55. ColorHigh: &xlsxTabColor{Theme: 6},
  56. ColorLow: &xlsxTabColor{Theme: 6},
  57. }, // 3
  58. {
  59. ColorSeries: &xlsxTabColor{Theme: 7, Tint: -0.499984740745262},
  60. ColorNegative: &xlsxTabColor{Theme: 8},
  61. ColorMarkers: &xlsxTabColor{Theme: 7, Tint: -0.499984740745262},
  62. ColorFirst: &xlsxTabColor{Theme: 7, Tint: 0.39997558519241921},
  63. ColorLast: &xlsxTabColor{Theme: 7, Tint: 0.39997558519241921},
  64. ColorHigh: &xlsxTabColor{Theme: 7},
  65. ColorLow: &xlsxTabColor{Theme: 7},
  66. }, // 4
  67. {
  68. ColorSeries: &xlsxTabColor{Theme: 8, Tint: -0.499984740745262},
  69. ColorNegative: &xlsxTabColor{Theme: 9},
  70. ColorMarkers: &xlsxTabColor{Theme: 8, Tint: -0.499984740745262},
  71. ColorFirst: &xlsxTabColor{Theme: 8, Tint: 0.39997558519241921},
  72. ColorLast: &xlsxTabColor{Theme: 8, Tint: 0.39997558519241921},
  73. ColorHigh: &xlsxTabColor{Theme: 8},
  74. ColorLow: &xlsxTabColor{Theme: 8},
  75. }, // 5
  76. {
  77. ColorSeries: &xlsxTabColor{Theme: 9, Tint: -0.499984740745262},
  78. ColorNegative: &xlsxTabColor{Theme: 4},
  79. ColorMarkers: &xlsxTabColor{Theme: 9, Tint: -0.499984740745262},
  80. ColorFirst: &xlsxTabColor{Theme: 9, Tint: 0.39997558519241921},
  81. ColorLast: &xlsxTabColor{Theme: 9, Tint: 0.39997558519241921},
  82. ColorHigh: &xlsxTabColor{Theme: 9},
  83. ColorLow: &xlsxTabColor{Theme: 9},
  84. }, // 6
  85. {
  86. ColorSeries: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  87. ColorNegative: &xlsxTabColor{Theme: 5},
  88. ColorMarkers: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  89. ColorFirst: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  90. ColorLast: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  91. ColorHigh: &xlsxTabColor{Theme: 5},
  92. ColorLow: &xlsxTabColor{Theme: 5},
  93. }, // 7
  94. {
  95. ColorSeries: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  96. ColorNegative: &xlsxTabColor{Theme: 6},
  97. ColorMarkers: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  98. ColorFirst: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  99. ColorLast: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  100. ColorHigh: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  101. ColorLow: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  102. }, // 8
  103. {
  104. ColorSeries: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  105. ColorNegative: &xlsxTabColor{Theme: 7},
  106. ColorMarkers: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  107. ColorFirst: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  108. ColorLast: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  109. ColorHigh: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  110. ColorLow: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  111. }, // 9
  112. {
  113. ColorSeries: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  114. ColorNegative: &xlsxTabColor{Theme: 8},
  115. ColorMarkers: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  116. ColorFirst: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  117. ColorLast: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  118. ColorHigh: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  119. ColorLow: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  120. }, // 10
  121. {
  122. ColorSeries: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  123. ColorNegative: &xlsxTabColor{Theme: 9},
  124. ColorMarkers: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  125. ColorFirst: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  126. ColorLast: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  127. ColorHigh: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  128. ColorLow: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  129. }, // 11
  130. {
  131. ColorSeries: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  132. ColorNegative: &xlsxTabColor{Theme: 4},
  133. ColorMarkers: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  134. ColorFirst: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  135. ColorLast: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  136. ColorHigh: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  137. ColorLow: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  138. }, // 12
  139. {
  140. ColorSeries: &xlsxTabColor{Theme: 4},
  141. ColorNegative: &xlsxTabColor{Theme: 5},
  142. ColorMarkers: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  143. ColorFirst: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  144. ColorLast: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  145. ColorHigh: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  146. ColorLow: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  147. }, // 13
  148. {
  149. ColorSeries: &xlsxTabColor{Theme: 5},
  150. ColorNegative: &xlsxTabColor{Theme: 6},
  151. ColorMarkers: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  152. ColorFirst: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  153. ColorLast: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  154. ColorHigh: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  155. ColorLow: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  156. }, // 14
  157. {
  158. ColorSeries: &xlsxTabColor{Theme: 6},
  159. ColorNegative: &xlsxTabColor{Theme: 7},
  160. ColorMarkers: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  161. ColorFirst: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  162. ColorLast: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  163. ColorHigh: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  164. ColorLow: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  165. }, // 15
  166. {
  167. ColorSeries: &xlsxTabColor{Theme: 7},
  168. ColorNegative: &xlsxTabColor{Theme: 8},
  169. ColorMarkers: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  170. ColorFirst: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  171. ColorLast: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  172. ColorHigh: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  173. ColorLow: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  174. }, // 16
  175. {
  176. ColorSeries: &xlsxTabColor{Theme: 8},
  177. ColorNegative: &xlsxTabColor{Theme: 9},
  178. ColorMarkers: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  179. ColorFirst: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  180. ColorLast: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  181. ColorHigh: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  182. ColorLow: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  183. }, // 17
  184. {
  185. ColorSeries: &xlsxTabColor{Theme: 9},
  186. ColorNegative: &xlsxTabColor{Theme: 4},
  187. ColorMarkers: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  188. ColorFirst: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  189. ColorLast: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  190. ColorHigh: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  191. ColorLow: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  192. }, // 18
  193. {
  194. ColorSeries: &xlsxTabColor{Theme: 4, Tint: 0.39997558519241921},
  195. ColorNegative: &xlsxTabColor{Theme: 0, Tint: -0.499984740745262},
  196. ColorMarkers: &xlsxTabColor{Theme: 4, Tint: 0.79998168889431442},
  197. ColorFirst: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  198. ColorLast: &xlsxTabColor{Theme: 4, Tint: -0.249977111117893},
  199. ColorHigh: &xlsxTabColor{Theme: 4, Tint: -0.499984740745262},
  200. ColorLow: &xlsxTabColor{Theme: 4, Tint: -0.499984740745262},
  201. }, // 19
  202. {
  203. ColorSeries: &xlsxTabColor{Theme: 5, Tint: 0.39997558519241921},
  204. ColorNegative: &xlsxTabColor{Theme: 0, Tint: -0.499984740745262},
  205. ColorMarkers: &xlsxTabColor{Theme: 5, Tint: 0.79998168889431442},
  206. ColorFirst: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  207. ColorLast: &xlsxTabColor{Theme: 5, Tint: -0.249977111117893},
  208. ColorHigh: &xlsxTabColor{Theme: 5, Tint: -0.499984740745262},
  209. ColorLow: &xlsxTabColor{Theme: 5, Tint: -0.499984740745262},
  210. }, // 20
  211. {
  212. ColorSeries: &xlsxTabColor{Theme: 6, Tint: 0.39997558519241921},
  213. ColorNegative: &xlsxTabColor{Theme: 0, Tint: -0.499984740745262},
  214. ColorMarkers: &xlsxTabColor{Theme: 6, Tint: 0.79998168889431442},
  215. ColorFirst: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  216. ColorLast: &xlsxTabColor{Theme: 6, Tint: -0.249977111117893},
  217. ColorHigh: &xlsxTabColor{Theme: 6, Tint: -0.499984740745262},
  218. ColorLow: &xlsxTabColor{Theme: 6, Tint: -0.499984740745262},
  219. }, // 21
  220. {
  221. ColorSeries: &xlsxTabColor{Theme: 7, Tint: 0.39997558519241921},
  222. ColorNegative: &xlsxTabColor{Theme: 0, Tint: -0.499984740745262},
  223. ColorMarkers: &xlsxTabColor{Theme: 7, Tint: 0.79998168889431442},
  224. ColorFirst: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  225. ColorLast: &xlsxTabColor{Theme: 7, Tint: -0.249977111117893},
  226. ColorHigh: &xlsxTabColor{Theme: 7, Tint: -0.499984740745262},
  227. ColorLow: &xlsxTabColor{Theme: 7, Tint: -0.499984740745262},
  228. }, // 22
  229. {
  230. ColorSeries: &xlsxTabColor{Theme: 8, Tint: 0.39997558519241921},
  231. ColorNegative: &xlsxTabColor{Theme: 0, Tint: -0.499984740745262},
  232. ColorMarkers: &xlsxTabColor{Theme: 8, Tint: 0.79998168889431442},
  233. ColorFirst: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  234. ColorLast: &xlsxTabColor{Theme: 8, Tint: -0.249977111117893},
  235. ColorHigh: &xlsxTabColor{Theme: 8, Tint: -0.499984740745262},
  236. ColorLow: &xlsxTabColor{Theme: 8, Tint: -0.499984740745262},
  237. }, // 23
  238. {
  239. ColorSeries: &xlsxTabColor{Theme: 9, Tint: 0.39997558519241921},
  240. ColorNegative: &xlsxTabColor{Theme: 0, Tint: -0.499984740745262},
  241. ColorMarkers: &xlsxTabColor{Theme: 9, Tint: 0.79998168889431442},
  242. ColorFirst: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  243. ColorLast: &xlsxTabColor{Theme: 9, Tint: -0.249977111117893},
  244. ColorHigh: &xlsxTabColor{Theme: 9, Tint: -0.499984740745262},
  245. ColorLow: &xlsxTabColor{Theme: 9, Tint: -0.499984740745262},
  246. }, // 24
  247. {
  248. ColorSeries: &xlsxTabColor{Theme: 1, Tint: 0.499984740745262},
  249. ColorNegative: &xlsxTabColor{Theme: 1, Tint: 0.249977111117893},
  250. ColorMarkers: &xlsxTabColor{Theme: 1, Tint: 0.249977111117893},
  251. ColorFirst: &xlsxTabColor{Theme: 1, Tint: 0.249977111117893},
  252. ColorLast: &xlsxTabColor{Theme: 1, Tint: 0.249977111117893},
  253. ColorHigh: &xlsxTabColor{Theme: 1, Tint: 0.249977111117893},
  254. ColorLow: &xlsxTabColor{Theme: 1, Tint: 0.249977111117893},
  255. }, // 25
  256. {
  257. ColorSeries: &xlsxTabColor{Theme: 1, Tint: 0.34998626667073579},
  258. ColorNegative: &xlsxTabColor{Theme: 0, Tint: 0.249977111117893},
  259. ColorMarkers: &xlsxTabColor{Theme: 0, Tint: 0.249977111117893},
  260. ColorFirst: &xlsxTabColor{Theme: 0, Tint: 0.249977111117893},
  261. ColorLast: &xlsxTabColor{Theme: 0, Tint: 0.249977111117893},
  262. ColorHigh: &xlsxTabColor{Theme: 0, Tint: 0.249977111117893},
  263. ColorLow: &xlsxTabColor{Theme: 0, Tint: 0.249977111117893},
  264. }, // 26
  265. {
  266. ColorSeries: &xlsxTabColor{RGB: "FF323232"},
  267. ColorNegative: &xlsxTabColor{RGB: "FFD00000"},
  268. ColorMarkers: &xlsxTabColor{RGB: "FFD00000"},
  269. ColorFirst: &xlsxTabColor{RGB: "FFD00000"},
  270. ColorLast: &xlsxTabColor{RGB: "FFD00000"},
  271. ColorHigh: &xlsxTabColor{RGB: "FFD00000"},
  272. ColorLow: &xlsxTabColor{RGB: "FFD00000"},
  273. }, // 27
  274. {
  275. ColorSeries: &xlsxTabColor{RGB: "FF000000"},
  276. ColorNegative: &xlsxTabColor{RGB: "FF0070C0"},
  277. ColorMarkers: &xlsxTabColor{RGB: "FF0070C0"},
  278. ColorFirst: &xlsxTabColor{RGB: "FF0070C0"},
  279. ColorLast: &xlsxTabColor{RGB: "FF0070C0"},
  280. ColorHigh: &xlsxTabColor{RGB: "FF0070C0"},
  281. ColorLow: &xlsxTabColor{RGB: "FF0070C0"},
  282. }, // 28
  283. {
  284. ColorSeries: &xlsxTabColor{RGB: "FF376092"},
  285. ColorNegative: &xlsxTabColor{RGB: "FFD00000"},
  286. ColorMarkers: &xlsxTabColor{RGB: "FFD00000"},
  287. ColorFirst: &xlsxTabColor{RGB: "FFD00000"},
  288. ColorLast: &xlsxTabColor{RGB: "FFD00000"},
  289. ColorHigh: &xlsxTabColor{RGB: "FFD00000"},
  290. ColorLow: &xlsxTabColor{RGB: "FFD00000"},
  291. }, // 29
  292. {
  293. ColorSeries: &xlsxTabColor{RGB: "FF0070C0"},
  294. ColorNegative: &xlsxTabColor{RGB: "FF000000"},
  295. ColorMarkers: &xlsxTabColor{RGB: "FF000000"},
  296. ColorFirst: &xlsxTabColor{RGB: "FF000000"},
  297. ColorLast: &xlsxTabColor{RGB: "FF000000"},
  298. ColorHigh: &xlsxTabColor{RGB: "FF000000"},
  299. ColorLow: &xlsxTabColor{RGB: "FF000000"},
  300. }, // 30
  301. {
  302. ColorSeries: &xlsxTabColor{RGB: "FF5F5F5F"},
  303. ColorNegative: &xlsxTabColor{RGB: "FFFFB620"},
  304. ColorMarkers: &xlsxTabColor{RGB: "FFD70077"},
  305. ColorFirst: &xlsxTabColor{RGB: "FF5687C2"},
  306. ColorLast: &xlsxTabColor{RGB: "FF359CEB"},
  307. ColorHigh: &xlsxTabColor{RGB: "FF56BE79"},
  308. ColorLow: &xlsxTabColor{RGB: "FFFF5055"},
  309. }, // 31
  310. {
  311. ColorSeries: &xlsxTabColor{RGB: "FF5687C2"},
  312. ColorNegative: &xlsxTabColor{RGB: "FFFFB620"},
  313. ColorMarkers: &xlsxTabColor{RGB: "FFD70077"},
  314. ColorFirst: &xlsxTabColor{RGB: "FF777777"},
  315. ColorLast: &xlsxTabColor{RGB: "FF359CEB"},
  316. ColorHigh: &xlsxTabColor{RGB: "FF56BE79"},
  317. ColorLow: &xlsxTabColor{RGB: "FFFF5055"},
  318. }, // 32
  319. {
  320. ColorSeries: &xlsxTabColor{RGB: "FFC6EFCE"},
  321. ColorNegative: &xlsxTabColor{RGB: "FFFFC7CE"},
  322. ColorMarkers: &xlsxTabColor{RGB: "FF8CADD6"},
  323. ColorFirst: &xlsxTabColor{RGB: "FFFFDC47"},
  324. ColorLast: &xlsxTabColor{RGB: "FFFFEB9C"},
  325. ColorHigh: &xlsxTabColor{RGB: "FF60D276"},
  326. ColorLow: &xlsxTabColor{RGB: "FFFF5367"},
  327. }, // 33
  328. {
  329. ColorSeries: &xlsxTabColor{RGB: "FF00B050"},
  330. ColorNegative: &xlsxTabColor{RGB: "FFFF0000"},
  331. ColorMarkers: &xlsxTabColor{RGB: "FF0070C0"},
  332. ColorFirst: &xlsxTabColor{RGB: "FFFFC000"},
  333. ColorLast: &xlsxTabColor{RGB: "FFFFC000"},
  334. ColorHigh: &xlsxTabColor{RGB: "FF00B050"},
  335. ColorLow: &xlsxTabColor{RGB: "FFFF0000"},
  336. }, // 34
  337. {
  338. ColorSeries: &xlsxTabColor{Theme: 3},
  339. ColorNegative: &xlsxTabColor{Theme: 9},
  340. ColorMarkers: &xlsxTabColor{Theme: 8},
  341. ColorFirst: &xlsxTabColor{Theme: 4},
  342. ColorLast: &xlsxTabColor{Theme: 5},
  343. ColorHigh: &xlsxTabColor{Theme: 6},
  344. ColorLow: &xlsxTabColor{Theme: 7},
  345. }, // 35
  346. {
  347. ColorSeries: &xlsxTabColor{Theme: 1},
  348. ColorNegative: &xlsxTabColor{Theme: 9},
  349. ColorMarkers: &xlsxTabColor{Theme: 8},
  350. ColorFirst: &xlsxTabColor{Theme: 4},
  351. ColorLast: &xlsxTabColor{Theme: 5},
  352. ColorHigh: &xlsxTabColor{Theme: 6},
  353. ColorLow: &xlsxTabColor{Theme: 7},
  354. }, // 36
  355. }
  356. return groups[ID]
  357. }
  358. // AddSparkline provides a function to add sparklines to the worksheet by
  359. // given formatting options. Sparklines are small charts that fit in a single
  360. // cell and are used to show trends in data. Sparklines are a feature of Excel
  361. // 2010 and later only. You can write them to an XLSX file that can be read by
  362. // Excel 2007, but they won't be displayed. For example, add a grouped
  363. // sparkline. Changes are applied to all three:
  364. //
  365. // err := f.AddSparkline("Sheet1", &excelize.SparklineOptions{
  366. // Location: []string{"A1", "A2", "A3"},
  367. // Range: []string{"Sheet2!A1:J1", "Sheet2!A2:J2", "Sheet2!A3:J3"},
  368. // Markers: true,
  369. // })
  370. //
  371. // The following shows the formatting options of sparkline supported by excelize:
  372. //
  373. // Parameter | Description
  374. // -------------+--------------------------------------------
  375. // Location | Required, must have the same number with 'Range' parameter
  376. // Range | Required, must have the same number with 'Location' parameter
  377. // Type | Enumeration value: line, column, win_loss
  378. // Style | Value range: 0 - 35
  379. // Hight | Toggle sparkline high points
  380. // Low | Toggle sparkline low points
  381. // First | Toggle sparkline first points
  382. // Last | Toggle sparkline last points
  383. // Negative | Toggle sparkline negative points
  384. // Markers | Toggle sparkline markers
  385. // Axis | Used to specify if show horizontal axis
  386. // Reverse | Used to specify if enable plot data right-to-left
  387. // SeriesColor | An RGB Color is specified as RRGGBB
  388. func (f *File) AddSparkline(sheet string, opts *SparklineOptions) error {
  389. var (
  390. err error
  391. ws *xlsxWorksheet
  392. sparkType string
  393. sparkTypes map[string]string
  394. specifiedSparkTypes string
  395. ok bool
  396. group *xlsxX14SparklineGroup
  397. groups *xlsxX14SparklineGroups
  398. )
  399. // parameter validation
  400. if ws, err = f.parseFormatAddSparklineSet(sheet, opts); err != nil {
  401. return err
  402. }
  403. // Handle the sparkline type
  404. sparkType = "line"
  405. sparkTypes = map[string]string{"line": "line", "column": "column", "win_loss": "stacked"}
  406. if opts.Type != "" {
  407. if specifiedSparkTypes, ok = sparkTypes[opts.Type]; !ok {
  408. err = ErrSparklineType
  409. return err
  410. }
  411. sparkType = specifiedSparkTypes
  412. }
  413. group = f.addSparklineGroupByStyle(opts.Style)
  414. group.Type = sparkType
  415. group.ColorAxis = &xlsxColor{RGB: "FF000000"}
  416. group.DisplayEmptyCellsAs = "gap"
  417. group.High = opts.High
  418. group.Low = opts.Low
  419. group.First = opts.First
  420. group.Last = opts.Last
  421. group.Negative = opts.Negative
  422. group.DisplayXAxis = opts.Axis
  423. group.Markers = opts.Markers
  424. if opts.SeriesColor != "" {
  425. group.ColorSeries = &xlsxTabColor{
  426. RGB: getPaletteColor(opts.SeriesColor),
  427. }
  428. }
  429. if opts.Reverse {
  430. group.RightToLeft = opts.Reverse
  431. }
  432. f.addSparkline(opts, group)
  433. if err = f.appendSparkline(ws, group, groups); err != nil {
  434. return err
  435. }
  436. f.addSheetNameSpace(sheet, NameSpaceSpreadSheetX14)
  437. return err
  438. }
  439. // parseFormatAddSparklineSet provides a function to validate sparkline
  440. // properties.
  441. func (f *File) parseFormatAddSparklineSet(sheet string, opts *SparklineOptions) (*xlsxWorksheet, error) {
  442. ws, err := f.workSheetReader(sheet)
  443. if err != nil {
  444. return ws, err
  445. }
  446. if opts == nil {
  447. return ws, ErrParameterRequired
  448. }
  449. if len(opts.Location) < 1 {
  450. return ws, ErrSparklineLocation
  451. }
  452. if len(opts.Range) < 1 {
  453. return ws, ErrSparklineRange
  454. }
  455. // The range and locations must match
  456. if len(opts.Location) != len(opts.Range) {
  457. return ws, ErrSparkline
  458. }
  459. if opts.Style < 0 || opts.Style > 35 {
  460. return ws, ErrSparklineStyle
  461. }
  462. if ws.ExtLst == nil {
  463. ws.ExtLst = &xlsxExtLst{}
  464. }
  465. return ws, err
  466. }
  467. // addSparkline provides a function to create a sparkline in a sparkline group
  468. // by given properties.
  469. func (f *File) addSparkline(opts *SparklineOptions, group *xlsxX14SparklineGroup) {
  470. for idx, location := range opts.Location {
  471. group.Sparklines.Sparkline = append(group.Sparklines.Sparkline, &xlsxX14Sparkline{
  472. F: opts.Range[idx],
  473. Sqref: location,
  474. })
  475. }
  476. }
  477. // appendSparkline provides a function to append sparkline to sparkline
  478. // groups.
  479. func (f *File) appendSparkline(ws *xlsxWorksheet, group *xlsxX14SparklineGroup, groups *xlsxX14SparklineGroups) error {
  480. var (
  481. err error
  482. idx int
  483. appendMode bool
  484. decodeExtLst = new(decodeWorksheetExt)
  485. decodeSparklineGroups *decodeX14SparklineGroups
  486. ext *xlsxWorksheetExt
  487. sparklineGroupsBytes, sparklineGroupBytes, extLstBytes []byte
  488. )
  489. sparklineGroupBytes, _ = xml.Marshal(group)
  490. if ws.ExtLst != nil { // append mode ext
  491. if err = f.xmlNewDecoder(strings.NewReader("<extLst>" + ws.ExtLst.Ext + "</extLst>")).
  492. Decode(decodeExtLst); err != nil && err != io.EOF {
  493. return err
  494. }
  495. for idx, ext = range decodeExtLst.Ext {
  496. if ext.URI == ExtURISparklineGroups {
  497. decodeSparklineGroups = new(decodeX14SparklineGroups)
  498. if err = f.xmlNewDecoder(strings.NewReader(ext.Content)).
  499. Decode(decodeSparklineGroups); err != nil && err != io.EOF {
  500. return err
  501. }
  502. if groups == nil {
  503. groups = &xlsxX14SparklineGroups{}
  504. }
  505. groups.XMLNSXM = NameSpaceSpreadSheetExcel2006Main.Value
  506. groups.Content = decodeSparklineGroups.Content + string(sparklineGroupBytes)
  507. sparklineGroupsBytes, _ = xml.Marshal(groups)
  508. decodeExtLst.Ext[idx].Content = string(sparklineGroupsBytes)
  509. appendMode = true
  510. }
  511. }
  512. }
  513. if !appendMode {
  514. sparklineGroupsBytes, _ = xml.Marshal(&xlsxX14SparklineGroups{
  515. XMLNSXM: NameSpaceSpreadSheetExcel2006Main.Value,
  516. SparklineGroups: []*xlsxX14SparklineGroup{group},
  517. })
  518. decodeExtLst.Ext = append(decodeExtLst.Ext, &xlsxWorksheetExt{
  519. URI: ExtURISparklineGroups, Content: string(sparklineGroupsBytes),
  520. })
  521. }
  522. sort.Slice(decodeExtLst.Ext, func(i, j int) bool {
  523. return inStrSlice(extensionURIPriority, decodeExtLst.Ext[i].URI, false) <
  524. inStrSlice(extensionURIPriority, decodeExtLst.Ext[j].URI, false)
  525. })
  526. extLstBytes, err = xml.Marshal(decodeExtLst)
  527. ws.ExtLst = &xlsxExtLst{Ext: strings.TrimSuffix(strings.TrimPrefix(string(extLstBytes), "<extLst>"), "</extLst>")}
  528. return err
  529. }