/app/lib/xlsxwriter/utility.py

https://bitbucket.org/Nitesh_Rajpurohit/app-engine · Python · 493 lines · 401 code · 46 blank · 46 comment · 25 complexity · 18f136c91bde1c1d237e27ee5356ae51 MD5 · raw file

  1. ###############################################################################
  2. #
  3. # Worksheet - A class for writing Excel Worksheets.
  4. #
  5. # Copyright 2013, John McNamara, jmcnamara@cpan.org
  6. #
  7. import re
  8. import sys
  9. from warnings import warn
  10. COL_NAMES = {}
  11. range_parts = re.compile(r'(\$?)([A-Z]{1,3})(\$?)(\d+)')
  12. def xl_rowcol_to_cell(row, col, row_abs=0, col_abs=0):
  13. """
  14. TODO. Add Utility.py docs.
  15. """
  16. row += 1 # Change to 1-index.
  17. row_abs = '$' if row_abs else ''
  18. col_abs = '$' if col_abs else ''
  19. col_str = xl_col_to_name(col, col_abs)
  20. return col_str + row_abs + str(row)
  21. def xl_rowcol_to_cell_fast(row, col):
  22. """
  23. Optimised version of the xl_rowcol_to_cell function.
  24. """
  25. if col in COL_NAMES:
  26. col_str = COL_NAMES[col]
  27. else:
  28. col_str = xl_col_to_name(col)
  29. COL_NAMES[col] = col_str
  30. return col_str + str(row + 1)
  31. def xl_col_to_name(col_num, col_abs=0):
  32. """
  33. TODO. Add Utility.py docs.
  34. """
  35. col_num += 1 # Change to 1-index.
  36. col_str = ''
  37. col_abs = '$' if col_abs else ''
  38. while col_num:
  39. # Set remainder from 1 .. 26
  40. remainder = col_num % 26
  41. if remainder == 0:
  42. remainder = 26
  43. # Convert the remainder to a character.
  44. col_letter = chr(ord('A') + remainder - 1)
  45. # Accumulate the column letters, right to left.
  46. col_str = col_letter + col_str
  47. # Get the next order of magnitude.
  48. col_num = int((col_num - 1) / 26)
  49. return col_abs + col_str
  50. def xl_cell_to_rowcol(cell_str):
  51. """
  52. TODO. Add Utility.py docs.
  53. """
  54. if not cell_str:
  55. return (0, 0)
  56. match = range_parts.match(cell_str)
  57. col_str = match.group(2)
  58. row_str = match.group(4)
  59. # Convert base26 column string to number.
  60. expn = 0
  61. col = 0
  62. for char in reversed(col_str):
  63. col += (ord(char) - ord('A') + 1) * (26 ** expn)
  64. expn += 1
  65. # Convert 1-index to zero-index
  66. row = int(row_str) - 1
  67. col -= 1
  68. return row, col
  69. def xl_cell_to_rowcol_abs(cell_str):
  70. """
  71. TODO. Add Utility.py docs.
  72. """
  73. if not cell_str:
  74. return (0, 0, 0, 0)
  75. match = range_parts.match(cell_str)
  76. col_abs = match.group(1)
  77. col_str = match.group(2)
  78. row_abs = match.group(3)
  79. row_str = match.group(4)
  80. if col_abs:
  81. col_abs = 1
  82. else:
  83. col_abs = 0
  84. if row_abs:
  85. row_abs = 1
  86. else:
  87. row_abs = 0
  88. # Convert base26 column string to number.
  89. expn = 0
  90. col = 0
  91. for char in reversed(col_str):
  92. col += (ord(char) - ord('A') + 1) * (26 ** expn)
  93. expn += 1
  94. # Convert 1-index to zero-index
  95. row = int(row_str) - 1
  96. col -= 1
  97. return row, col, row_abs, col_abs
  98. def xl_range(first_row, first_col, last_row, last_col):
  99. """
  100. TODO. Add Utility.py docs.
  101. """
  102. range1 = xl_rowcol_to_cell(first_row, first_col)
  103. range2 = xl_rowcol_to_cell(last_row, last_col)
  104. return range1 + ':' + range2
  105. def xl_color(color):
  106. # Used in conjunction with the XlsxWriter *color() methods to convert
  107. # a colour name into an RGB formatted string. These colours are for
  108. # backward compatibility with older versions of Excel.
  109. named_colors = {
  110. 'black': '#000000',
  111. 'blue': '#0000FF',
  112. 'brown': '#800000',
  113. 'cyan': '#00FFFF',
  114. 'gray': '#808080',
  115. 'green': '#008000',
  116. 'lime': '#00FF00',
  117. 'magenta': '#FF00FF',
  118. 'navy': '#000080',
  119. 'orange': '#FF6600',
  120. 'pink': '#FF00FF',
  121. 'purple': '#800080',
  122. 'red': '#FF0000',
  123. 'silver': '#C0C0C0',
  124. 'white': '#FFFFFF',
  125. 'yellow': '#FFFF00',
  126. }
  127. if color in named_colors:
  128. color = named_colors[color]
  129. if not re.match('#[0-9a-fA-F]{6}', color):
  130. warn("Color '%s' isn't a valid Excel color" % color)
  131. # Convert the RGB color to the Excel ARGB format.
  132. return "FF" + color.lstrip('#').upper()
  133. def get_sparkline_style(style_id):
  134. styles = [
  135. {'series': {'theme': "4", 'tint': "-0.499984740745262"},
  136. 'negative': {'theme': "5"},
  137. 'markers': {'theme': "4", 'tint': "-0.499984740745262"},
  138. 'first': {'theme': "4", 'tint': "0.39997558519241921"},
  139. 'last': {'theme': "4", 'tint': "0.39997558519241921"},
  140. 'high': {'theme': "4"},
  141. 'low': {'theme': "4"},
  142. }, # 0
  143. {'series': {'theme': "4", 'tint': "-0.499984740745262"},
  144. 'negative': {'theme': "5"},
  145. 'markers': {'theme': "4", 'tint': "-0.499984740745262"},
  146. 'first': {'theme': "4", 'tint': "0.39997558519241921"},
  147. 'last': {'theme': "4", 'tint': "0.39997558519241921"},
  148. 'high': {'theme': "4"},
  149. 'low': {'theme': "4"},
  150. }, # 1
  151. {'series': {'theme': "5", 'tint': "-0.499984740745262"},
  152. 'negative': {'theme': "6"},
  153. 'markers': {'theme': "5", 'tint': "-0.499984740745262"},
  154. 'first': {'theme': "5", 'tint': "0.39997558519241921"},
  155. 'last': {'theme': "5", 'tint': "0.39997558519241921"},
  156. 'high': {'theme': "5"},
  157. 'low': {'theme': "5"},
  158. }, # 2
  159. {'series': {'theme': "6", 'tint': "-0.499984740745262"},
  160. 'negative': {'theme': "7"},
  161. 'markers': {'theme': "6", 'tint': "-0.499984740745262"},
  162. 'first': {'theme': "6", 'tint': "0.39997558519241921"},
  163. 'last': {'theme': "6", 'tint': "0.39997558519241921"},
  164. 'high': {'theme': "6"},
  165. 'low': {'theme': "6"},
  166. }, # 3
  167. {'series': {'theme': "7", 'tint': "-0.499984740745262"},
  168. 'negative': {'theme': "8"},
  169. 'markers': {'theme': "7", 'tint': "-0.499984740745262"},
  170. 'first': {'theme': "7", 'tint': "0.39997558519241921"},
  171. 'last': {'theme': "7", 'tint': "0.39997558519241921"},
  172. 'high': {'theme': "7"},
  173. 'low': {'theme': "7"},
  174. }, # 4
  175. {'series': {'theme': "8", 'tint': "-0.499984740745262"},
  176. 'negative': {'theme': "9"},
  177. 'markers': {'theme': "8", 'tint': "-0.499984740745262"},
  178. 'first': {'theme': "8", 'tint': "0.39997558519241921"},
  179. 'last': {'theme': "8", 'tint': "0.39997558519241921"},
  180. 'high': {'theme': "8"},
  181. 'low': {'theme': "8"},
  182. }, # 5
  183. {'series': {'theme': "9", 'tint': "-0.499984740745262"},
  184. 'negative': {'theme': "4"},
  185. 'markers': {'theme': "9", 'tint': "-0.499984740745262"},
  186. 'first': {'theme': "9", 'tint': "0.39997558519241921"},
  187. 'last': {'theme': "9", 'tint': "0.39997558519241921"},
  188. 'high': {'theme': "9"},
  189. 'low': {'theme': "9"},
  190. }, # 6
  191. {'series': {'theme': "4", 'tint': "-0.249977111117893"},
  192. 'negative': {'theme': "5"},
  193. 'markers': {'theme': "5", 'tint': "-0.249977111117893"},
  194. 'first': {'theme': "5", 'tint': "-0.249977111117893"},
  195. 'last': {'theme': "5", 'tint': "-0.249977111117893"},
  196. 'high': {'theme': "5", 'tint': "-0.249977111117893"},
  197. 'low': {'theme': "5", 'tint': "-0.249977111117893"},
  198. }, # 7
  199. {'series': {'theme': "5", 'tint': "-0.249977111117893"},
  200. 'negative': {'theme': "6"},
  201. 'markers': {'theme': "6", 'tint': "-0.249977111117893"},
  202. 'first': {'theme': "6", 'tint': "-0.249977111117893"},
  203. 'last': {'theme': "6", 'tint': "-0.249977111117893"},
  204. 'high': {'theme': "6", 'tint': "-0.249977111117893"},
  205. 'low': {'theme': "6", 'tint': "-0.249977111117893"},
  206. }, # 8
  207. {'series': {'theme': "6", 'tint': "-0.249977111117893"},
  208. 'negative': {'theme': "7"},
  209. 'markers': {'theme': "7", 'tint': "-0.249977111117893"},
  210. 'first': {'theme': "7", 'tint': "-0.249977111117893"},
  211. 'last': {'theme': "7", 'tint': "-0.249977111117893"},
  212. 'high': {'theme': "7", 'tint': "-0.249977111117893"},
  213. 'low': {'theme': "7", 'tint': "-0.249977111117893"},
  214. }, # 9
  215. {'series': {'theme': "7", 'tint': "-0.249977111117893"},
  216. 'negative': {'theme': "8"},
  217. 'markers': {'theme': "8", 'tint': "-0.249977111117893"},
  218. 'first': {'theme': "8", 'tint': "-0.249977111117893"},
  219. 'last': {'theme': "8", 'tint': "-0.249977111117893"},
  220. 'high': {'theme': "8", 'tint': "-0.249977111117893"},
  221. 'low': {'theme': "8", 'tint': "-0.249977111117893"},
  222. }, # 10
  223. {'series': {'theme': "8", 'tint': "-0.249977111117893"},
  224. 'negative': {'theme': "9"},
  225. 'markers': {'theme': "9", 'tint': "-0.249977111117893"},
  226. 'first': {'theme': "9", 'tint': "-0.249977111117893"},
  227. 'last': {'theme': "9", 'tint': "-0.249977111117893"},
  228. 'high': {'theme': "9", 'tint': "-0.249977111117893"},
  229. 'low': {'theme': "9", 'tint': "-0.249977111117893"},
  230. }, # 11
  231. {'series': {'theme': "9", 'tint': "-0.249977111117893"},
  232. 'negative': {'theme': "4"},
  233. 'markers': {'theme': "4", 'tint': "-0.249977111117893"},
  234. 'first': {'theme': "4", 'tint': "-0.249977111117893"},
  235. 'last': {'theme': "4", 'tint': "-0.249977111117893"},
  236. 'high': {'theme': "4", 'tint': "-0.249977111117893"},
  237. 'low': {'theme': "4", 'tint': "-0.249977111117893"},
  238. }, # 12
  239. {'series': {'theme': "4"},
  240. 'negative': {'theme': "5"},
  241. 'markers': {'theme': "4", 'tint': "-0.249977111117893"},
  242. 'first': {'theme': "4", 'tint': "-0.249977111117893"},
  243. 'last': {'theme': "4", 'tint': "-0.249977111117893"},
  244. 'high': {'theme': "4", 'tint': "-0.249977111117893"},
  245. 'low': {'theme': "4", 'tint': "-0.249977111117893"},
  246. }, # 13
  247. {'series': {'theme': "5"},
  248. 'negative': {'theme': "6"},
  249. 'markers': {'theme': "5", 'tint': "-0.249977111117893"},
  250. 'first': {'theme': "5", 'tint': "-0.249977111117893"},
  251. 'last': {'theme': "5", 'tint': "-0.249977111117893"},
  252. 'high': {'theme': "5", 'tint': "-0.249977111117893"},
  253. 'low': {'theme': "5", 'tint': "-0.249977111117893"},
  254. }, # 14
  255. {'series': {'theme': "6"},
  256. 'negative': {'theme': "7"},
  257. 'markers': {'theme': "6", 'tint': "-0.249977111117893"},
  258. 'first': {'theme': "6", 'tint': "-0.249977111117893"},
  259. 'last': {'theme': "6", 'tint': "-0.249977111117893"},
  260. 'high': {'theme': "6", 'tint': "-0.249977111117893"},
  261. 'low': {'theme': "6", 'tint': "-0.249977111117893"},
  262. }, # 15
  263. {'series': {'theme': "7"},
  264. 'negative': {'theme': "8"},
  265. 'markers': {'theme': "7", 'tint': "-0.249977111117893"},
  266. 'first': {'theme': "7", 'tint': "-0.249977111117893"},
  267. 'last': {'theme': "7", 'tint': "-0.249977111117893"},
  268. 'high': {'theme': "7", 'tint': "-0.249977111117893"},
  269. 'low': {'theme': "7", 'tint': "-0.249977111117893"},
  270. }, # 16
  271. {'series': {'theme': "8"},
  272. 'negative': {'theme': "9"},
  273. 'markers': {'theme': "8", 'tint': "-0.249977111117893"},
  274. 'first': {'theme': "8", 'tint': "-0.249977111117893"},
  275. 'last': {'theme': "8", 'tint': "-0.249977111117893"},
  276. 'high': {'theme': "8", 'tint': "-0.249977111117893"},
  277. 'low': {'theme': "8", 'tint': "-0.249977111117893"},
  278. }, # 17
  279. {'series': {'theme': "9"},
  280. 'negative': {'theme': "4"},
  281. 'markers': {'theme': "9", 'tint': "-0.249977111117893"},
  282. 'first': {'theme': "9", 'tint': "-0.249977111117893"},
  283. 'last': {'theme': "9", 'tint': "-0.249977111117893"},
  284. 'high': {'theme': "9", 'tint': "-0.249977111117893"},
  285. 'low': {'theme': "9", 'tint': "-0.249977111117893"},
  286. }, # 18
  287. {'series': {'theme': "4", 'tint': "0.39997558519241921"},
  288. 'negative': {'theme': "0", 'tint': "-0.499984740745262"},
  289. 'markers': {'theme': "4", 'tint': "0.79998168889431442"},
  290. 'first': {'theme': "4", 'tint': "-0.249977111117893"},
  291. 'last': {'theme': "4", 'tint': "-0.249977111117893"},
  292. 'high': {'theme': "4", 'tint': "-0.499984740745262"},
  293. 'low': {'theme': "4", 'tint': "-0.499984740745262"},
  294. }, # 19
  295. {'series': {'theme': "5", 'tint': "0.39997558519241921"},
  296. 'negative': {'theme': "0", 'tint': "-0.499984740745262"},
  297. 'markers': {'theme': "5", 'tint': "0.79998168889431442"},
  298. 'first': {'theme': "5", 'tint': "-0.249977111117893"},
  299. 'last': {'theme': "5", 'tint': "-0.249977111117893"},
  300. 'high': {'theme': "5", 'tint': "-0.499984740745262"},
  301. 'low': {'theme': "5", 'tint': "-0.499984740745262"},
  302. }, # 20
  303. {'series': {'theme': "6", 'tint': "0.39997558519241921"},
  304. 'negative': {'theme': "0", 'tint': "-0.499984740745262"},
  305. 'markers': {'theme': "6", 'tint': "0.79998168889431442"},
  306. 'first': {'theme': "6", 'tint': "-0.249977111117893"},
  307. 'last': {'theme': "6", 'tint': "-0.249977111117893"},
  308. 'high': {'theme': "6", 'tint': "-0.499984740745262"},
  309. 'low': {'theme': "6", 'tint': "-0.499984740745262"},
  310. }, # 21
  311. {'series': {'theme': "7", 'tint': "0.39997558519241921"},
  312. 'negative': {'theme': "0", 'tint': "-0.499984740745262"},
  313. 'markers': {'theme': "7", 'tint': "0.79998168889431442"},
  314. 'first': {'theme': "7", 'tint': "-0.249977111117893"},
  315. 'last': {'theme': "7", 'tint': "-0.249977111117893"},
  316. 'high': {'theme': "7", 'tint': "-0.499984740745262"},
  317. 'low': {'theme': "7", 'tint': "-0.499984740745262"},
  318. }, # 22
  319. {'series': {'theme': "8", 'tint': "0.39997558519241921"},
  320. 'negative': {'theme': "0", 'tint': "-0.499984740745262"},
  321. 'markers': {'theme': "8", 'tint': "0.79998168889431442"},
  322. 'first': {'theme': "8", 'tint': "-0.249977111117893"},
  323. 'last': {'theme': "8", 'tint': "-0.249977111117893"},
  324. 'high': {'theme': "8", 'tint': "-0.499984740745262"},
  325. 'low': {'theme': "8", 'tint': "-0.499984740745262"},
  326. }, # 23
  327. {'series': {'theme': "9", 'tint': "0.39997558519241921"},
  328. 'negative': {'theme': "0", 'tint': "-0.499984740745262"},
  329. 'markers': {'theme': "9", 'tint': "0.79998168889431442"},
  330. 'first': {'theme': "9", 'tint': "-0.249977111117893"},
  331. 'last': {'theme': "9", 'tint': "-0.249977111117893"},
  332. 'high': {'theme': "9", 'tint': "-0.499984740745262"},
  333. 'low': {'theme': "9", 'tint': "-0.499984740745262"},
  334. }, # 24
  335. {'series': {'theme': "1", 'tint': "0.499984740745262"},
  336. 'negative': {'theme': "1", 'tint': "0.249977111117893"},
  337. 'markers': {'theme': "1", 'tint': "0.249977111117893"},
  338. 'first': {'theme': "1", 'tint': "0.249977111117893"},
  339. 'last': {'theme': "1", 'tint': "0.249977111117893"},
  340. 'high': {'theme': "1", 'tint': "0.249977111117893"},
  341. 'low': {'theme': "1", 'tint': "0.249977111117893"},
  342. }, # 25
  343. {'series': {'theme': "1", 'tint': "0.34998626667073579"},
  344. 'negative': {'theme': "0", 'tint': "-0.249977111117893"},
  345. 'markers': {'theme': "0", 'tint': "-0.249977111117893"},
  346. 'first': {'theme': "0", 'tint': "-0.249977111117893"},
  347. 'last': {'theme': "0", 'tint': "-0.249977111117893"},
  348. 'high': {'theme': "0", 'tint': "-0.249977111117893"},
  349. 'low': {'theme': "0", 'tint': "-0.249977111117893"},
  350. }, # 26
  351. {'series': {'rgb': "FF323232"},
  352. 'negative': {'rgb': "FFD00000"},
  353. 'markers': {'rgb': "FFD00000"},
  354. 'first': {'rgb': "FFD00000"},
  355. 'last': {'rgb': "FFD00000"},
  356. 'high': {'rgb': "FFD00000"},
  357. 'low': {'rgb': "FFD00000"},
  358. }, # 27
  359. {'series': {'rgb': "FF000000"},
  360. 'negative': {'rgb': "FF0070C0"},
  361. 'markers': {'rgb': "FF0070C0"},
  362. 'first': {'rgb': "FF0070C0"},
  363. 'last': {'rgb': "FF0070C0"},
  364. 'high': {'rgb': "FF0070C0"},
  365. 'low': {'rgb': "FF0070C0"},
  366. }, # 28
  367. {'series': {'rgb': "FF376092"},
  368. 'negative': {'rgb': "FFD00000"},
  369. 'markers': {'rgb': "FFD00000"},
  370. 'first': {'rgb': "FFD00000"},
  371. 'last': {'rgb': "FFD00000"},
  372. 'high': {'rgb': "FFD00000"},
  373. 'low': {'rgb': "FFD00000"},
  374. }, # 29
  375. {'series': {'rgb': "FF0070C0"},
  376. 'negative': {'rgb': "FF000000"},
  377. 'markers': {'rgb': "FF000000"},
  378. 'first': {'rgb': "FF000000"},
  379. 'last': {'rgb': "FF000000"},
  380. 'high': {'rgb': "FF000000"},
  381. 'low': {'rgb': "FF000000"},
  382. }, # 30
  383. {'series': {'rgb': "FF5F5F5F"},
  384. 'negative': {'rgb': "FFFFB620"},
  385. 'markers': {'rgb': "FFD70077"},
  386. 'first': {'rgb': "FF5687C2"},
  387. 'last': {'rgb': "FF359CEB"},
  388. 'high': {'rgb': "FF56BE79"},
  389. 'low': {'rgb': "FFFF5055"},
  390. }, # 31
  391. {'series': {'rgb': "FF5687C2"},
  392. 'negative': {'rgb': "FFFFB620"},
  393. 'markers': {'rgb': "FFD70077"},
  394. 'first': {'rgb': "FF777777"},
  395. 'last': {'rgb': "FF359CEB"},
  396. 'high': {'rgb': "FF56BE79"},
  397. 'low': {'rgb': "FFFF5055"},
  398. }, # 32
  399. {'series': {'rgb': "FFC6EFCE"},
  400. 'negative': {'rgb': "FFFFC7CE"},
  401. 'markers': {'rgb': "FF8CADD6"},
  402. 'first': {'rgb': "FFFFDC47"},
  403. 'last': {'rgb': "FFFFEB9C"},
  404. 'high': {'rgb': "FF60D276"},
  405. 'low': {'rgb': "FFFF5367"},
  406. }, # 33
  407. {'series': {'rgb': "FF00B050"},
  408. 'negative': {'rgb': "FFFF0000"},
  409. 'markers': {'rgb': "FF0070C0"},
  410. 'first': {'rgb': "FFFFC000"},
  411. 'last': {'rgb': "FFFFC000"},
  412. 'high': {'rgb': "FF00B050"},
  413. 'low': {'rgb': "FFFF0000"},
  414. }, # 34
  415. {'series': {'theme': "3"},
  416. 'negative': {'theme': "9"},
  417. 'markers': {'theme': "8"},
  418. 'first': {'theme': "4"},
  419. 'last': {'theme': "5"},
  420. 'high': {'theme': "6"},
  421. 'low': {'theme': "7"},
  422. }, # 35
  423. {'series': {'theme': "1"},
  424. 'negative': {'theme': "9"},
  425. 'markers': {'theme': "8"},
  426. 'first': {'theme': "4"},
  427. 'last': {'theme': "5"},
  428. 'high': {'theme': "6"},
  429. 'low': {'theme': "7"},
  430. }, # 36
  431. ]
  432. return styles[style_id]
  433. def encode_utf8(string):
  434. """
  435. Encode any strings passed by the user to UTF8 in Python 2.
  436. """
  437. if string is None or sys.version_info >= (3, 0):
  438. return string
  439. else:
  440. return string.encode('utf-8')