ExportUtils.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. using FastReport.Format;
  2. using FastReport.Utils;
  3. using System;
  4. using System.ComponentModel;
  5. using System.Drawing;
  6. using System.Drawing.Imaging;
  7. using System.Globalization;
  8. using System.IO;
  9. using System.IO.Compression;
  10. using System.Text;
  11. namespace FastReport.Export
  12. {
  13. /// <summary>
  14. /// For internal use only.
  15. /// </summary>
  16. public static class ExportUtils
  17. {
  18. internal const string XCONV = "0123456789ABCDEF";
  19. private const int BASE = 65521;
  20. private const int NMAX = 5552;
  21. internal enum CRLF
  22. {
  23. html,
  24. xml,
  25. odt
  26. };
  27. /// <summary>
  28. /// Gets current page width.
  29. /// </summary>
  30. /// <param name="page"></param>
  31. /// <returns></returns>
  32. public static float GetPageWidth(ReportPage page)
  33. {
  34. if (page.UnlimitedWidth)
  35. return page.UnlimitedWidthValue / Units.Millimeters;
  36. else
  37. return page.PaperWidth;
  38. }
  39. /// <summary>
  40. /// Gets current page height.
  41. /// </summary>
  42. /// <param name="page"></param>
  43. /// <returns></returns>
  44. public static float GetPageHeight(ReportPage page)
  45. {
  46. if (page.UnlimitedHeight)
  47. return page.UnlimitedHeightValue / Units.Millimeters;
  48. else
  49. return page.PaperHeight;
  50. }
  51. private static readonly NumberFormatInfo _provider;
  52. public static string FloatToString(double value, int digits = 2)
  53. {
  54. return Convert.ToString(Math.Round(value, digits), _provider);
  55. }
  56. internal static bool ParseTextToDecimal(string text, FormatBase format, out decimal value)
  57. {
  58. value = 0;
  59. if (format is NumberFormat)
  60. {
  61. return decimal.TryParse(text, NumberStyles.Number, (format as NumberFormat).GetNumberFormatInfo(), out value);
  62. }
  63. else if (format is CurrencyFormat)
  64. {
  65. return decimal.TryParse(text, NumberStyles.Currency, (format as CurrencyFormat).GetNumberFormatInfo(), out value);
  66. }
  67. else if (format is CustomFormat && !(format is DateFormat))
  68. {
  69. return decimal.TryParse(text, out value);
  70. }
  71. return false;
  72. }
  73. internal static bool ParseTextToDateTime(string text, FormatBase format, out DateTime value)
  74. {
  75. value = DateTime.MinValue;
  76. if (format is DateFormat)
  77. return DateTime.TryParse(text, CultureInfo.CurrentCulture.DateTimeFormat, DateTimeStyles.None, out value);
  78. return false;
  79. }
  80. internal static bool ParseTextToPercent(string text, FormatBase format, out decimal value)
  81. {
  82. value = 0;
  83. if (format is PercentFormat)
  84. {
  85. bool returned = decimal.TryParse(text.Replace("%", ""), out value);
  86. value /= 100;
  87. return returned;
  88. }
  89. return false;
  90. }
  91. internal static string GetExcelFormatSpecifier(FormatBase format, bool useLocale = false, bool currencyToAccounting = false)
  92. {
  93. if (format is CurrencyFormat)
  94. {
  95. NumberFormatInfo f = (format as CurrencyFormat).GetNumberFormatInfo();
  96. if (useLocale)
  97. {
  98. (format as CurrencyFormat).UseLocale = true;
  99. f = (format as CurrencyFormat).GetNumberFormatInfo();
  100. f.CurrencyDecimalDigits = CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalDigits;
  101. }
  102. string fm_str = "#,##0";
  103. if (f.CurrencyDecimalDigits > 0)
  104. {
  105. fm_str += ".";// f.DecimalSeparator;
  106. for (int i = 0; i < f.CurrencyDecimalDigits; i++)
  107. fm_str += "0";
  108. }
  109. string currency_symbol = "&quot;" + f.CurrencySymbol + "&quot;";
  110. string positive_pattern = "";
  111. string negative_pattern = "";
  112. switch (f.CurrencyPositivePattern)
  113. {
  114. case 0: positive_pattern = currency_symbol + fm_str; break; // $n
  115. case 1: positive_pattern = fm_str + currency_symbol; break; // n$
  116. case 2: positive_pattern = currency_symbol + " " + fm_str; break; // $ n
  117. case 3: positive_pattern = fm_str + " " + currency_symbol; break; // n $
  118. }
  119. switch (f.CurrencyNegativePattern)
  120. {
  121. case 0: negative_pattern = "(" + currency_symbol + fm_str + ")"; break; // ($n)
  122. case 1: negative_pattern = "-" + currency_symbol + fm_str; break; // -$n
  123. case 2: negative_pattern = currency_symbol + "-" + fm_str; break; // $-n
  124. case 3: negative_pattern = currency_symbol + fm_str + "-"; break; // $n-
  125. case 4: negative_pattern = "(" + currency_symbol + fm_str + ")"; break; // (n$)
  126. case 5: negative_pattern = "-" + fm_str + currency_symbol; break; // -n$
  127. case 6: negative_pattern = fm_str + "-" + currency_symbol; break; // n-$
  128. case 7: negative_pattern = fm_str + currency_symbol + "-"; break; // n$-
  129. case 8: negative_pattern = "-" + fm_str + " " + currency_symbol; break; // -n $
  130. case 9: negative_pattern = "-" + currency_symbol + " " + fm_str; break; // -$ n
  131. case 10: negative_pattern = fm_str + " " + currency_symbol + "-"; break; // n $-
  132. case 11: negative_pattern = currency_symbol + " " + fm_str + "-"; break; // $ n-
  133. case 12: negative_pattern = currency_symbol + " -" + fm_str; break; // $ -n
  134. case 13: negative_pattern = fm_str + "- " + currency_symbol; break; // n- $
  135. case 14: negative_pattern = "(" + currency_symbol + " " + fm_str + ")"; break; // ($ n)
  136. case 15: negative_pattern = "(" + fm_str + " " + currency_symbol + ")"; break; // (n $)
  137. }
  138. if (currencyToAccounting)
  139. {
  140. string financeSymbol = "";
  141. switch (f.CurrencySymbol)
  142. {
  143. case "₽": financeSymbol = "[$₽-419]"; break;
  144. case "$": financeSymbol = "[$$-409]"; break;
  145. case "\u20AC": financeSymbol = "[$€-2]"; break;
  146. case "\u00A3": financeSymbol = "[$£-809]"; break;
  147. case "\u20B9": financeSymbol = "[$₹-4009]"; break;
  148. }
  149. switch (f.CurrencyPositivePattern)
  150. {
  151. case 0: positive_pattern = @"_-* " + financeSymbol + fm_str + "_-;"; break; // $n
  152. case 1: positive_pattern = @"_-* " + fm_str + financeSymbol + "_-;"; break; // n$
  153. case 2: positive_pattern = @"_-* " + financeSymbol + " " + fm_str + "_-;"; break; // $ n
  154. case 3: positive_pattern = @"_-* " + fm_str + " " + financeSymbol + "_-;"; break; // n $
  155. }
  156. switch (f.CurrencyNegativePattern)
  157. {
  158. case 0: negative_pattern = @"_-* " + "(" + financeSymbol + fm_str + ")" + "_-;"; break; // ($n)
  159. case 1: negative_pattern = @"_-* " + "-" + financeSymbol + fm_str + "_-;"; break; // -$n
  160. case 2: negative_pattern = @"_-* " + financeSymbol + "-" + fm_str + "_-;"; break; // $-n
  161. case 3: negative_pattern = @"_-* " + financeSymbol + fm_str + "-" + "_-;"; break; // $n-
  162. case 4: negative_pattern = @"_-* " + "(" + fm_str + financeSymbol + ")" + "_-;"; break; // (n$)
  163. case 5: negative_pattern = @"_-* " + "-" + fm_str + financeSymbol + "_-;"; break; // -n$
  164. case 6: negative_pattern = @"_-* " + fm_str + "-" + financeSymbol + "_-;"; break; // n-$
  165. case 7: negative_pattern = @"_-* " + fm_str + financeSymbol + "-" + "_-;"; break; // n$-
  166. case 8: negative_pattern = @"_-* " + "-" + fm_str + " " + financeSymbol + "_-;"; break; // -n $
  167. case 9: negative_pattern = @"_-* " + "-" + financeSymbol + " " + fm_str + "_-;"; break; // -$ n
  168. case 10: negative_pattern = @"_-* " + fm_str + " " + financeSymbol + "-" + "_-;"; break; // n $-
  169. case 11: negative_pattern = @"_-* " + financeSymbol + " " + fm_str + "-" + "_-;"; break; // $ n-
  170. case 12: negative_pattern = @"_-* " + financeSymbol + " " + "-" + fm_str + "_-;"; break; // $ -n
  171. case 13: negative_pattern = @"_-* " + fm_str + "- " + financeSymbol + "_-;"; break; // n- $
  172. case 14: negative_pattern = @"_-* " + "(" + financeSymbol + " " + fm_str + ")" + "_-;"; break; // ($ n)
  173. case 15: negative_pattern = @"_-* " + "(" + fm_str + " " + financeSymbol + ")" + "_-;"; break; // (n $)
  174. }
  175. string financeFormat_Options = @"_-* &quot;-&quot;??\ " + financeSymbol + "_-;_-@_-";
  176. return positive_pattern + negative_pattern + financeFormat_Options;
  177. }
  178. return positive_pattern + ";" + negative_pattern;
  179. }
  180. else if (format is NumberFormat)
  181. {
  182. NumberFormatInfo f = (format as NumberFormat).GetNumberFormatInfo();
  183. if (useLocale)
  184. {
  185. (format as NumberFormat).UseLocale = true;
  186. f = (format as NumberFormat).GetNumberFormatInfo();
  187. f.CurrencyDecimalDigits = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalDigits;
  188. }
  189. string fm_str = "#,##0";
  190. if (f.NumberDecimalDigits > 0)
  191. {
  192. fm_str += ".";// f.DecimalSeparator;
  193. for (int i = 0; i < f.NumberDecimalDigits; i++)
  194. fm_str += "0";
  195. }
  196. string positive_pattern = "";
  197. string negative_pattern = "";
  198. positive_pattern = fm_str;
  199. switch (f.NumberNegativePattern)
  200. {
  201. case 0: negative_pattern = "(" + fm_str + ")"; break; // (n)
  202. case 1: negative_pattern = "-" + fm_str; break; // -n
  203. case 2: negative_pattern = "- " + fm_str; break; // - n
  204. case 3: negative_pattern = fm_str + "-"; break; // n-
  205. case 4: negative_pattern = fm_str + " -"; break; // n -
  206. }
  207. return positive_pattern + ";" + negative_pattern;
  208. }
  209. else if (format is DateFormat)
  210. {
  211. string parentalCase = CultureInfo.CurrentCulture.TwoLetterISOLanguageName == "ru" ? "[$-FC19]" : "";
  212. switch ((format as DateFormat).Format)
  213. {
  214. case "d": return DateTimeFormatInfo.CurrentInfo.ShortDatePattern + ";@";
  215. case "D": return "[$-F800]" + DateTimeFormatInfo.CurrentInfo.LongDatePattern.Replace("tt", "AM/PM") + ";@";
  216. case "f": return parentalCase + (DateTimeFormatInfo.CurrentInfo.LongDatePattern + " " + DateTimeFormatInfo.CurrentInfo.ShortTimePattern).Replace("tt", "AM/PM") + ";@";
  217. case "F": return parentalCase + DateTimeFormatInfo.CurrentInfo.FullDateTimePattern.Replace("tt", "AM/PM") + ";@";
  218. case "MMMM yyyy": return (format as DateFormat).Format + ";@";
  219. default: return parentalCase + (format as DateFormat).Format.Replace("tt", "AM/PM") + ";@";
  220. }
  221. }
  222. else if (format is PercentFormat)
  223. {
  224. string pattern = "0";
  225. if (useLocale)
  226. {
  227. (format as PercentFormat).UseLocale = true;
  228. (format as PercentFormat).DecimalDigits = CultureInfo.CurrentCulture.NumberFormat.PercentDecimalDigits;
  229. }
  230. if ((format as PercentFormat).DecimalDigits > 0)
  231. {
  232. pattern += ".";
  233. for (int i = 0; i < (format as PercentFormat).DecimalDigits; i++)
  234. pattern += "0";
  235. }
  236. return pattern + "%";
  237. }
  238. return "";
  239. }
  240. internal static string HTMLColor(Color color)
  241. {
  242. return ColorTranslator.ToHtml(color);
  243. }
  244. internal static string HTMLColorCode(Color color)
  245. {
  246. return String.Join(String.Empty, new String[] {
  247. "#",
  248. color.R.ToString("X2"),
  249. color.G.ToString("X2"),
  250. color.B.ToString("X2")
  251. });
  252. }
  253. internal static string ByteToHex(byte Byte)
  254. {
  255. char[] s = new char[2];
  256. s[0] = XCONV[(Byte >> 4)];
  257. s[1] = XCONV[(Byte & 0xF)];
  258. return new String(s);
  259. }
  260. internal static string UInt16Tohex(UInt16 word)
  261. {
  262. FastString sb = new FastString(4);
  263. return sb.Append(ByteToHex((byte)((word >> 8) & 0xFF))).Append(ByteToHex((byte)(word & 0xFF))).ToString();
  264. }
  265. internal static string TruncReturns(string Str)
  266. {
  267. if (Str.EndsWith("\r\n"))
  268. return Str.Substring(0, Str.Length - 2);
  269. else
  270. return Str;
  271. }
  272. internal static FastString HtmlString(string text)
  273. {
  274. return HtmlString(text, TextRenderType.Default);
  275. }
  276. internal static FastString HtmlString(string text, TextRenderType textRenderType, CRLF crlf, bool excel2007, string fontSize = "13px;")
  277. {
  278. FastString Result = new FastString(text.Length);
  279. int len = text.Length;
  280. int lineBreakCount = 0;
  281. if (textRenderType == TextRenderType.HtmlTags)
  282. {
  283. const string wingdings = "<font face=\"Wingdings\">";
  284. const string webdings = "<font face=\"Webdings\">";
  285. int ind1 = 0, ind2 = 0;
  286. if (text.Contains(wingdings))
  287. {
  288. ind1 = text.IndexOf(wingdings) + wingdings.Length;
  289. ind2 = text.IndexOf('<', ind1);
  290. text = text.Substring(0, ind1) +
  291. WingdingsToUnicodeConverter.Convert(text.Substring(ind1, ind2 - ind1)) +
  292. text.Substring(ind2, text.Length - ind2);
  293. }
  294. else if (text.Contains(webdings))
  295. {
  296. ind1 = text.IndexOf(webdings) + webdings.Length;
  297. ind2 = text.IndexOf('<', ind1);
  298. text = text.Substring(0, ind1) +
  299. WingdingsToUnicodeConverter.Convert(text.Substring(ind1, ind2 - ind1)) +
  300. text.Substring(ind2, text.Length - ind2);
  301. }
  302. }
  303. for (int i = 0; i < len; i++)
  304. {
  305. if (crlf != CRLF.xml && crlf != CRLF.odt && text[i] == ' ' && (text.Length == 1 ||
  306. (i < (len - 1) && text[i + 1] == ' ') ||
  307. (i > 0 && text[i - 1] == ' ')
  308. || i == len - 1))
  309. {
  310. Result.Append("&nbsp;");
  311. }
  312. else if (text[i] == '<' && textRenderType == TextRenderType.HtmlTags && crlf == CRLF.odt)
  313. i += text.IndexOf('>', i) - i;
  314. else if (i < text.Length - 1 && (text[i] == '\r' && text[i + 1] == '\n'))
  315. {
  316. if (crlf == CRLF.xml)
  317. Result.Append("&#10;");
  318. else if (crlf == CRLF.odt)
  319. Result.Append("<text:line-break />");
  320. else
  321. {
  322. if ((i == 0 && text[i] == '\r' && text[i + 1] == '\n'))
  323. Result.Append($"<p style=\"margin-top:{fontSize}margin-bottom:0px\"></p>");
  324. if (lineBreakCount == 0)
  325. Result.Append("<p style=\"margin-top:0px;margin-bottom:0px;\"></p>");
  326. else
  327. Result.Append($"<p style=\"margin-top:0px;height:{fontSize}margin-bottom:0px\"></p>");
  328. lineBreakCount++;
  329. }
  330. i++;
  331. }
  332. else
  333. {
  334. lineBreakCount = 0;
  335. if (text[i] == '\t' && crlf == CRLF.odt)
  336. Result.Append("<text:tab/>");
  337. else if (text[i] == ' ' && crlf == CRLF.odt)
  338. {
  339. int spaces = 1;
  340. while (i < text.Length - 1)
  341. {
  342. if (text[i + 1] == ' ')
  343. {
  344. i++;
  345. spaces++;
  346. }
  347. else
  348. break;
  349. }
  350. Result.Append("<text:s text:c=\"" + spaces + "\"/>");
  351. }
  352. else if (text[i] == '\\')
  353. Result.Append("&#92;");
  354. else if (text[i] == '~' && !excel2007)
  355. Result.Append("&tilde;");
  356. else if (text[i] == '€' && !excel2007)
  357. Result.Append("&euro;");
  358. else if (text[i] == '‹' && !excel2007)
  359. Result.Append("&lsaquo;");
  360. else if (text[i] == '›' && !excel2007)
  361. Result.Append("&rsaquo;");
  362. else if (text[i] == 'ˆ' && !excel2007)
  363. Result.Append("&circ;");
  364. else if (text[i] == '&' && textRenderType == TextRenderType.Default)
  365. Result.Append("&amp;");
  366. else if (text[i] == '"' && textRenderType == TextRenderType.Default)
  367. Result.Append("&quot;");
  368. else if (text[i] == '<' && textRenderType == TextRenderType.Default)
  369. Result.Append("&lt;");
  370. else if (text[i] == '>' && textRenderType == TextRenderType.Default)
  371. Result.Append("&gt;");
  372. else if (text[i] == '\t' && excel2007)
  373. Result.Append("&#9;");
  374. else
  375. Result.Append(text[i]);
  376. }
  377. }
  378. return Result;
  379. }
  380. internal static string QuotedPrintable(byte[] Values)
  381. {
  382. FastString sb = new FastString((int)(Values.Length * 1.3));
  383. int length = 0;
  384. foreach (byte c in Values)
  385. {
  386. if (length > 73)
  387. {
  388. length = 0;
  389. sb.Append('=').AppendLine();
  390. }
  391. if (c < 9 || c == 61 || c > 126)
  392. {
  393. sb.Append('=').Append(XCONV[c >> 4]).Append(XCONV[c & 0xF]);
  394. length += 3;
  395. }
  396. else
  397. {
  398. sb.Append((char)c);
  399. length++;
  400. }
  401. }
  402. return sb.ToString();
  403. }
  404. public static FastString HtmlString(string text, TextRenderType textRenderType, string fontSize = "13px;")
  405. {
  406. return HtmlString(text, textRenderType, CRLF.html, false, fontSize);
  407. }
  408. internal static string XmlString(string Str, TextRenderType textRenderType)
  409. {
  410. return HtmlString(Str, textRenderType, CRLF.xml, false).ToString();
  411. }
  412. internal static string Excel2007String(string Str, TextRenderType textRenderType)
  413. {
  414. return HtmlString(Str, textRenderType, CRLF.xml, true).ToString();
  415. }
  416. internal static string OdtString(string Str, TextRenderType textRenderType)
  417. {
  418. return HtmlString(Str, textRenderType, CRLF.odt, false).ToString();
  419. }
  420. /// <summary>
  421. ///
  422. /// </summary>
  423. /// <param name="Value"></param>
  424. /// <returns></returns>
  425. internal static string HtmlURL(string Value)
  426. {
  427. FastString Result = new FastString();
  428. #if DOTNET_4
  429. foreach (char c in Value)
  430. {
  431. if (!char.IsLetterOrDigit(c) && !char.IsPunctuation(c))
  432. Result.Append("%").Append(Convert.ToInt32(c).ToString("x"));
  433. else
  434. Result.Append(c);
  435. }
  436. #else
  437. for (int i = 0; i < Value.Length; i++)
  438. {
  439. switch (Value[i])
  440. {
  441. case '\\':
  442. Result.Append("/");
  443. break;
  444. case '&':
  445. case '<':
  446. case '>':
  447. case '{':
  448. case '}':
  449. case ';':
  450. case '?':
  451. case ' ':
  452. case '\'':
  453. case '"':
  454. Result.Append("%" + ExportUtils.ByteToHex((byte)Value[i]));
  455. break;
  456. default:
  457. Result.Append(Value[i]);
  458. break;
  459. }
  460. }
  461. #endif
  462. return Result.ToString();
  463. }
  464. internal static void Write(Stream stream, string value)
  465. {
  466. byte[] buf = Encoding.UTF8.GetBytes(value);
  467. stream.Write(buf, 0, buf.Length);
  468. }
  469. internal static void WriteLn(Stream stream, string value)
  470. {
  471. byte[] buf = Encoding.UTF8.GetBytes(value);
  472. stream.Write(buf, 0, buf.Length);
  473. stream.WriteByte(13);
  474. stream.WriteByte(10);
  475. }
  476. internal static void Write(Stream stream, byte value)
  477. {
  478. stream.WriteByte(value);
  479. }
  480. internal static void Write(Stream stream, StringBuilder value)
  481. {
  482. byte[] buf = Encoding.UTF8.GetBytes(value.ToString());
  483. stream.Write(buf, 0, buf.Length);
  484. }
  485. internal static void WriteLn(Stream stream, StringBuilder value)
  486. {
  487. byte[] buf = Encoding.UTF8.GetBytes(value.ToString());
  488. stream.Write(buf, 0, buf.Length);
  489. stream.WriteByte(13);
  490. stream.WriteByte(10);
  491. }
  492. internal static void ZLibDeflate(Stream src, Stream dst)
  493. {
  494. dst.WriteByte(0x78);
  495. dst.WriteByte(0xDA);
  496. src.Position = 0;
  497. long adler = 1L;
  498. using (DeflateStream compressor = new DeflateStream(dst, CompressionMode.Compress, true))
  499. {
  500. const int bufflength = 2048;
  501. byte[] buff = new byte[bufflength];
  502. int i;
  503. while ((i = src.Read(buff, 0, bufflength)) > 0)
  504. {
  505. adler = Adler32(adler, buff, 0, i);
  506. compressor.Write(buff, 0, i);
  507. }
  508. }
  509. dst.WriteByte((byte)(adler >> 24 & 0xFF));
  510. dst.WriteByte((byte)(adler >> 16 & 0xFF));
  511. dst.WriteByte((byte)(adler >> 8 & 0xFF));
  512. dst.WriteByte((byte)(adler & 0xFF));
  513. }
  514. internal static long Adler32(long adler, byte[] buf, int index, int len)
  515. {
  516. if (buf == null) { return 1L; }
  517. long s1 = adler & 0xffff;
  518. long s2 = (adler >> 16) & 0xffff;
  519. int k;
  520. while (len > 0)
  521. {
  522. k = len < NMAX ? len : NMAX;
  523. len -= k;
  524. while (k >= 16)
  525. {
  526. s1 += buf[index++] & 0xff; s2 += s1;
  527. s1 += buf[index++] & 0xff; s2 += s1;
  528. s1 += buf[index++] & 0xff; s2 += s1;
  529. s1 += buf[index++] & 0xff; s2 += s1;
  530. s1 += buf[index++] & 0xff; s2 += s1;
  531. s1 += buf[index++] & 0xff; s2 += s1;
  532. s1 += buf[index++] & 0xff; s2 += s1;
  533. s1 += buf[index++] & 0xff; s2 += s1;
  534. s1 += buf[index++] & 0xff; s2 += s1;
  535. s1 += buf[index++] & 0xff; s2 += s1;
  536. s1 += buf[index++] & 0xff; s2 += s1;
  537. s1 += buf[index++] & 0xff; s2 += s1;
  538. s1 += buf[index++] & 0xff; s2 += s1;
  539. s1 += buf[index++] & 0xff; s2 += s1;
  540. s1 += buf[index++] & 0xff; s2 += s1;
  541. s1 += buf[index++] & 0xff; s2 += s1;
  542. k -= 16;
  543. }
  544. if (k != 0)
  545. {
  546. do
  547. {
  548. s1 += buf[index++] & 0xff;
  549. s2 += s1;
  550. }
  551. while (--k != 0);
  552. }
  553. s1 %= BASE;
  554. s2 %= BASE;
  555. }
  556. return (s2 << 16) | s1;
  557. }
  558. internal static string ReverseString(string str)
  559. {
  560. FastString result = new FastString(str.Length);
  561. int i, j;
  562. for (j = 0, i = str.Length - 1; i >= 0; i--, j++)
  563. result.Append(str[i]);
  564. return result.ToString();
  565. }
  566. internal static string StrToHex(string s)
  567. {
  568. FastString sb = new FastString(s.Length * 2);
  569. foreach (char c in s)
  570. sb.Append(((byte)c).ToString("X2"));
  571. return sb.ToString();
  572. }
  573. internal static FastString StrToHex2(string s)
  574. {
  575. FastString sb = new FastString(s.Length * 2);
  576. foreach (char c in s)
  577. sb.Append(((UInt16)c).ToString("X4"));
  578. return sb;
  579. }
  580. internal static string GetID()
  581. {
  582. return SystemFake.Guid.NewGuid().ToString();
  583. }
  584. internal static byte[] StringToByteArray(string source)
  585. {
  586. byte[] result = new byte[source.Length];
  587. for (int i = 0; i < source.Length; i++)
  588. result[i] = (byte)source[i];
  589. return result;
  590. }
  591. internal static byte[] StringTo2ByteArray(string source)
  592. {
  593. byte[] result = new byte[source.Length * 2];
  594. for (int i = 0; i < source.Length; i++)
  595. {
  596. result[i] = (byte)(source[i] >> 8);
  597. result[i + 1] = (byte)source[i];
  598. }
  599. return result;
  600. }
  601. internal static string StringFromByteArray(byte[] array)
  602. {
  603. FastString result = new FastString(array.Length);
  604. foreach (byte b in array)
  605. result.Append((char)b);
  606. return result.ToString();
  607. }
  608. internal static Color GetColorFromFill(FillBase Fill)
  609. {
  610. if (Fill is SolidFill)
  611. return (Fill as SolidFill).Color;
  612. else if (Fill is GlassFill)
  613. return (Fill as GlassFill).Color;
  614. else if (Fill is HatchFill)
  615. return (Fill as HatchFill).BackColor;
  616. else if (Fill is PathGradientFill)
  617. return (Fill as PathGradientFill).CenterColor;
  618. else if (Fill is LinearGradientFill)
  619. return GetMiddleColor((Fill as LinearGradientFill).StartColor, (Fill as LinearGradientFill).EndColor);
  620. else
  621. return Color.White;
  622. }
  623. private static Color GetMiddleColor(Color color1, Color color2)
  624. {
  625. return Color.FromArgb(255,
  626. (color1.R + color2.R) / 2,
  627. (color1.G + color2.G) / 2,
  628. (color1.B + color2.B) / 2);
  629. }
  630. internal static string GetRFCDate(DateTime datetime)
  631. {
  632. FastString sb = new FastString();
  633. sb.AppendFormat("{0:R}", datetime);
  634. int hours = TimeZone.CurrentTimeZone.GetUtcOffset(datetime).Hours;
  635. int minutes = TimeZone.CurrentTimeZone.GetUtcOffset(datetime).Minutes;
  636. if (hours == 0 && minutes == 0)
  637. return sb.ToString();
  638. else
  639. {
  640. string offset = (hours >= 0 && minutes >= 0 ? "+" : "") + hours.ToString("00") + minutes.ToString("00");
  641. return sb.ToString().Replace("GMT", offset);
  642. }
  643. }
  644. internal static ImageCodecInfo GetCodec(string codec)
  645. {
  646. foreach (ImageCodecInfo ice in ImageCodecInfo.GetImageEncoders())
  647. {
  648. if (ice.MimeType == codec)
  649. return ice;
  650. }
  651. return null;
  652. }
  653. /// <summary>
  654. /// For developers only
  655. /// </summary>
  656. [EditorBrowsable(EditorBrowsableState.Advanced)]
  657. public static void SaveJpeg(System.Drawing.Image image, Stream buff, int quality)
  658. {
  659. ImageCodecInfo ici = ExportUtils.GetCodec("image/jpeg");
  660. EncoderParameters ep = new EncoderParameters();
  661. ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
  662. image.Save(buff, ici, ep);
  663. }
  664. internal static string TruncLeadSlash(string line)
  665. {
  666. line = line.Replace("\\", "/");
  667. if (line.StartsWith("/"))
  668. return line.Remove(0, 1);
  669. else
  670. return line;
  671. }
  672. internal static string GetCellReference(int x, int y)
  673. {
  674. StringBuilder cellReference = new StringBuilder(4);
  675. const int MAX_CHARS = 'Z' - 'A' + 1;
  676. do
  677. {
  678. if (cellReference.Length > 0)
  679. x--;
  680. int digit = x % MAX_CHARS;
  681. char cellDig = (char)((char)'A' + (char)digit);
  682. cellReference.Append(cellDig);
  683. x -= digit;
  684. x /= (MAX_CHARS);
  685. }
  686. while (x > 0);
  687. for (int i = 0; i < cellReference.Length / 2; i++)
  688. {
  689. char c = cellReference[i];
  690. cellReference[i] = cellReference[cellReference.Length - i - 1];
  691. cellReference[cellReference.Length - i - 1] = c;
  692. }
  693. cellReference.Append(y.ToString());
  694. return cellReference.ToString();
  695. }
  696. private static readonly CultureInfo INVARIANT_CULTURE = CultureInfo.InvariantCulture;
  697. internal static string StringFormat(string formatString, params object[] objects)
  698. {
  699. return String.Format(INVARIANT_CULTURE, formatString, objects);
  700. }
  701. /// <summary>
  702. /// Convert index to Excel column name.
  703. /// </summary>
  704. /// <param name="index"> Index of column</param>
  705. /// <returns> Column name</returns>
  706. public static string IndexToName(int index)
  707. {
  708. bool firstSymbol = false;
  709. string result = "";
  710. for (; index > 0; index /= 26)
  711. {
  712. if (index < 26 && result != "")
  713. firstSymbol = true;
  714. var x = index % 26;
  715. result = (char)(x + 'A' + (firstSymbol ? -1 : 0)) + result;
  716. }
  717. if (result == "")
  718. result = "A";
  719. return result;
  720. }
  721. static ExportUtils()
  722. {
  723. var defaultProvider = new NumberFormatInfo();
  724. defaultProvider.NumberGroupSeparator = string.Empty;
  725. defaultProvider.NumberDecimalSeparator = ".";
  726. _provider = NumberFormatInfo.ReadOnly(defaultProvider);
  727. }
  728. }
  729. }