using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; using OfficeOpenXml.FormulaParsing.ExpressionGraph; using System.IO; namespace OfficeOpenXml.Utils { internal static class ConvertUtil { internal static bool IsNumeric(object candidate) { if (candidate == null) return false; return (candidate.GetType().IsPrimitive || candidate is double || candidate is decimal || candidate is DateTime || candidate is TimeSpan || candidate is long); } internal static bool IsNumericString(object candidate) { if (candidate != null) { return Regex.IsMatch(candidate.ToString(), @"^[\d]+(\,[\d])?"); } return false; } /// /// Convert an object value to a double /// /// /// /// internal static double GetValueDouble(object v, bool ignoreBool = false) { double d; try { if (ignoreBool && v is bool) { return 0; } if (IsNumeric(v)) { if (v is DateTime) { d = ((DateTime)v).ToOADate(); } else if (v is TimeSpan) { d = DateTime.FromOADate(0).Add((TimeSpan)v).ToOADate(); } else { d = Convert.ToDouble(v, CultureInfo.InvariantCulture); } } else { d = 0; } } catch { d = 0; } return d; } /// /// OOXML requires that "," , and & be escaped, but ' and " should *not* be escaped, nor should /// any extended Unicode characters. This function only encodes the required characters. /// System.Security.SecurityElement.Escape() escapes ' and " as ' and ", so it cannot /// be used reliably. System.Web.HttpUtility.HtmlEncode overreaches as well and uses the numeric /// escape equivalent. /// /// /// internal static string ExcelEscapeString(string s) { return s.Replace("&", "&").Replace("<", "<").Replace(">", ">"); } /// /// Return true if preserve space attribute is set. /// /// /// /// internal static void ExcelEncodeString(StreamWriter sw, string t) { if (Regex.IsMatch(t, "(_x[0-9A-F]{4,4}_)")) { var match = Regex.Match(t, "(_x[0-9A-F]{4,4}_)"); int indexAdd = 0; while (match.Success) { t = t.Insert(match.Index + indexAdd, "_x005F"); indexAdd += 6; match = match.NextMatch(); } } for (int i = 0; i < t.Length; i++) { if (t[i] <= 0x1f && t[i] != '\t' && t[i] != '\n' && t[i] != '\r') //Not Tab, CR or LF { sw.Write("_x00{0}_", (t[i] < 0xa ? "0" : "") + ((int)t[i]).ToString("X")); } else { sw.Write(t[i]); } } } /// /// Return true if preserve space attribute is set. /// /// /// /// internal static void ExcelEncodeString(StringBuilder sb, string t) { if (Regex.IsMatch(t, "(_x[0-9A-F]{4,4}_)")) { var match = Regex.Match(t, "(_x[0-9A-F]{4,4}_)"); int indexAdd = 0; while (match.Success) { t = t.Insert(match.Index + indexAdd, "_x005F"); indexAdd += 6; match = match.NextMatch(); } } for (int i = 0; i < t.Length; i++) { if (t[i] <= 0x1f && t[i] != '\t' && t[i] != '\n' && t[i] != '\r') //Not Tab, CR or LF { sb.AppendFormat("_x00{0}_", (t[i] < 0xa ? "0" : "") + ((int)t[i]).ToString("X")); } else { sb.Append(t[i]); } } } internal static string ExcelDecodeString(string t) { var match = Regex.Match(t, "(_x005F|_x[0-9A-F]{4,4}_)"); if (!match.Success) return t; var useNextValue = false; var ret = new StringBuilder(); var prevIndex = 0; while (match.Success) { if (prevIndex < match.Index) ret.Append(t.Substring(prevIndex, match.Index - prevIndex)); if (!useNextValue && match.Value == "_x005F") { useNextValue = true; } else { if (useNextValue) { ret.Append(match.Value); useNextValue = false; } else { ret.Append((char)int.Parse(match.Value.Substring(2, 4), NumberStyles.AllowHexSpecifier)); } } prevIndex = match.Index + match.Length; match = match.NextMatch(); } ret.Append(t.Substring(prevIndex, t.Length - prevIndex)); return ret.ToString(); } } }