using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Xml; using System.Xml.Linq; namespace Npoi.Core { public static class ExcelExtensions { public static XElement CreateElement(this XDocument element, string name) { return new XElement(name); } public static string GetAttribute(this XElement element, string name, string sub = null) { return element.Attribute(name)?.Value ?? sub; } public static void AppendChild(this XElement element, object content) { element.Add(content); } public static void AppendChild(this XDocument element, object content) { element.Add(content); } public static XElement CloneNode(this XElement element, bool deep) { return element; } public static XAttribute GetAttributeNode(this XElement root, string name) { return root.Attribute(name); } public static ConstructorInfo FilterConstructorsByType(this IEnumerable constructors, params Type[] types) { foreach (var item in constructors) { var paramsInfo = item.GetParameters().Select(x => x.ParameterType.FullName); var typesInfo = types.Select(x => x.FullName); var isThis = paramsInfo.Except(typesInfo).Count()==0; if (isThis) { return item; } } return constructors.First(); } // This function is duplicated in COMDateTime.cpp // Number of 100ns ticks per time unit private const long TicksPerMillisecond = 10000; private const long TicksPerSecond = TicksPerMillisecond * 1000; private const long TicksPerMinute = TicksPerSecond * 60; private const long TicksPerHour = TicksPerMinute * 60; private const long TicksPerDay = TicksPerHour * 24; // Number of milliseconds per time unit private const int MillisPerSecond = 1000; private const int MillisPerMinute = MillisPerSecond * 60; private const int MillisPerHour = MillisPerMinute * 60; private const int MillisPerDay = MillisPerHour * 24; // Number of days in a non-leap year private const int DaysPerYear = 365; // Number of days in 4 years private const int DaysPer4Years = DaysPerYear * 4 + 1; // Number of days in 100 years private const int DaysPer100Years = DaysPer4Years * 25 - 1; // Number of days in 400 years private const int DaysPer400Years = DaysPer100Years * 4 + 1; private const int DaysTo1899 = DaysPer400Years * 4 + DaysPer100Years * 3 - 367; private const long DoubleDateOffset = DaysTo1899 * TicksPerDay; private const long OADateMinAsTicks = (DaysPer100Years - DaysPerYear) * TicksPerDay; private static double TicksToOADate(long value) { if (value == 0) return 0.0; // Returns OleAut's zero'ed date value. if (value < TicksPerDay) // This is a fix for VB. They want the default day to be 1/1/0001 rathar then 12/30/1899. value += DoubleDateOffset; // We could have moved this fix down but we would like to keep the bounds check. if (value < OADateMinAsTicks) throw new OverflowException("Arg_OleAutDateInvalid"); // Currently, our max date == OA's max date (12/31/9999), so we don't // need an overflow check in that direction. long millis = (value - DoubleDateOffset) / TicksPerMillisecond; if (millis < 0) { long frac = millis % MillisPerDay; if (frac != 0) millis -= (MillisPerDay + frac) * 2; } return (double)millis / MillisPerDay; } #if !NET46 public static double ToOADate(this DateTime root) { return TicksToOADate(root.Ticks); } #endif public static string OuterXml(this XElement root) { using (var reader = root.CreateReader()) { reader.MoveToContent(); return reader.ReadOuterXml(); } } public static string OuterXml(this XNode root) { using (var reader = root.CreateReader()) { reader.MoveToContent(); return reader.ReadOuterXml(); } } public static string InnerXml(this XElement root) { using (var reader = root.CreateReader()) { reader.MoveToContent(); return reader.ReadInnerXml(); } } public static string Prefix(this XElement root) { return root.GetPrefixOfNamespace(root.Name.Namespace); } public static IEnumerable ChildElements(this XElement root) { foreach (XNode childNode in root.Nodes()) { var elm = childNode as XElement; if (elm != null) { yield return elm; } } } public static string AttributeValue(this XElement element, string attribute, string sub = null) { return element.Attribute(attribute).Value ?? sub; } //public static XElement SetAttribute(this XElement root, string name, string value) //{ // var nsAttribute = // new XAttribute(name, value); // root.Add(nsAttribute); // return root; //} public static XmlNameTable NameTable(this XDocument doc) { using (var reader = doc.CreateReader()) { return reader.NameTable; } } public static XElement SetAttribute(this XElement root, string name, XNamespace schema, string value) { var nsAttribute = new XAttribute(schema + name, value); root.Add(nsAttribute); return root; } } }