ExportUtils.cs 32 KB

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