Free cookie consent management tool by TermsFeed Policy Generator

source: branches/ExportSymbolicDataAnalysisSolutions/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/3.1.3/EPPlus-3.1.3/Style/XmlAccess/ExcelNumberFormatXml.cs @ 9580

Last change on this file since 9580 was 9580, checked in by sforsten, 11 years ago

#1730:

  • added SymbolicDataAnalysisExpressionExcelFormatter
  • changed modifiers in SymbolicExpressionTreeChart of methods SaveImageAsBitmap and SaveImageAsEmf to public
  • added menu item ExportSymbolicSolutionToExcelMenuItem to export a symbolic solution to an excel file
  • added EPPlus-3.1.3 to ExtLibs
File size: 27.2 KB
Line 
1/*******************************************************************************
2 * You may amend and distribute as you like, but don't remove this header!
3 *
4 * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
5 * See http://www.codeplex.com/EPPlus for details.
6 *
7 * Copyright (C) 2011  Jan Källman
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
17 * See the GNU Lesser General Public License for more details.
18 *
19 * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
20 * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
21 *
22 * All code and executables are provided "as is" with no warranty either express or implied.
23 * The author accepts no liability for any damage or loss of business that this product may cause.
24 *
25 * Code change notes:
26 *
27 * Author             Change            Date
28 * ******************************************************************************
29 * Jan Källman                    Initial Release           2009-10-01
30 * Jan Källman    License changed GPL-->LGPL 2011-12-16
31 *******************************************************************************/
32using System;
33using System.Collections.Generic;
34using System.Text;
35using System.Xml;
36using System.Globalization;
37using System.Text.RegularExpressions;
38namespace OfficeOpenXml.Style.XmlAccess
39{
40    /// <summary>
41    /// Xml access class for number formats
42    /// </summary>
43    public sealed class ExcelNumberFormatXml : StyleXmlHelper
44    {
45        internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager) : base(nameSpaceManager)
46        {
47           
48        }       
49        internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager, bool buildIn): base(nameSpaceManager)
50        {
51            BuildIn = buildIn;
52        }
53        internal ExcelNumberFormatXml(XmlNamespaceManager nsm, XmlNode topNode) :
54            base(nsm, topNode)
55        {
56            _numFmtId = GetXmlNodeInt("@numFmtId");
57            _format = GetXmlNodeString("@formatCode");
58        }
59        public bool BuildIn { get; private set; }
60        int _numFmtId;
61//        const string idPath = "@numFmtId";
62        /// <summary>
63        /// Id for number format
64        ///
65        /// Build in ID's
66        ///
67        /// 0   General
68        /// 1   0
69        /// 2   0.00
70        /// 3   #,##0
71        /// 4   #,##0.00
72        /// 9   0%
73        /// 10  0.00%
74        /// 11  0.00E+00
75        /// 12  # ?/?
76        /// 13  # ??/??
77        /// 14  mm-dd-yy
78        /// 15  d-mmm-yy
79        /// 16  d-mmm
80        /// 17  mmm-yy
81        /// 18  h:mm AM/PM
82        /// 19  h:mm:ss AM/PM
83        /// 20  h:mm
84        /// 21  h:mm:ss
85        /// 22  m/d/yy h:mm
86        /// 37  #,##0 ;(#,##0)
87        /// 38  #,##0 ;[Red](#,##0)
88        /// 39  #,##0.00;(#,##0.00)
89        /// 40  #,##0.00;[Red](#,##0.00)
90        /// 45  mm:ss
91        /// 46  [h]:mm:ss
92        /// 47  mmss.0
93        /// 48  ##0.0E+0
94        /// 49  @
95        /// </summary>           
96        public int NumFmtId
97        {
98            get
99            {
100                return _numFmtId;
101            }
102            set
103            {
104                _numFmtId = value;
105            }
106        }
107        internal override string Id
108        {
109            get
110            {
111                return _format;
112            }
113        }
114        const string fmtPath = "@formatCode";
115        string _format = string.Empty;
116        public string Format
117        {
118            get
119            {
120                return _format;
121            }
122            set
123            {
124                _numFmtId = ExcelNumberFormat.GetFromBuildIdFromFormat(value);
125                _format = value;
126            }
127        }
128        internal string GetNewID(int NumFmtId, string Format)
129        {
130           
131            if (NumFmtId < 0)
132            {
133                NumFmtId = ExcelNumberFormat.GetFromBuildIdFromFormat(Format);               
134            }
135            return NumFmtId.ToString();
136        }
137
138        internal static void AddBuildIn(XmlNamespaceManager NameSpaceManager, ExcelStyleCollection<ExcelNumberFormatXml> NumberFormats)
139        {
140            NumberFormats.Add("General",new ExcelNumberFormatXml(NameSpaceManager,true){NumFmtId=0,Format="General"});
141            NumberFormats.Add("0", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 1, Format = "0" });
142            NumberFormats.Add("0.00", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 2, Format = "0.00" });
143            NumberFormats.Add("#,##0", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 3, Format = "#,##0" });
144            NumberFormats.Add("#,##0.00", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 4, Format = "#,##0.00" });
145            NumberFormats.Add("0%", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 9, Format = "0%" });
146            NumberFormats.Add("0.00%", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 10, Format = "0.00%" });
147            NumberFormats.Add("0.00E+00", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 11, Format = "0.00E+00" });
148            NumberFormats.Add("# ?/?", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 12, Format = "# ?/?" });
149            NumberFormats.Add("# ??/??", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 13, Format = "# ??/??" });
150            NumberFormats.Add("mm-dd-yy", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 14, Format = "mm-dd-yy" });
151            NumberFormats.Add("d-mmm-yy", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 15, Format = "d-mmm-yy" });
152            NumberFormats.Add("d-mmm", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 16, Format = "d-mmm" });
153            NumberFormats.Add("mmm-yy", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 17, Format = "mmm-yy" });
154            NumberFormats.Add("h:mm AM/PM", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 18, Format = "h:mm AM/PM" });
155            NumberFormats.Add("h:mm:ss AM/PM", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 19, Format = "h:mm:ss AM/PM" });
156            NumberFormats.Add("h:mm", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 20, Format = "h:mm" });
157            NumberFormats.Add("h:mm:dd", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 21, Format = "h:mm:dd" });
158            NumberFormats.Add("m/d/yy h:mm", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 22, Format = "m/d/yy h:mm" });
159            NumberFormats.Add("#,##0 ;(#,##0)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 37, Format = "#,##0 ;(#,##0)" });
160            NumberFormats.Add("#,##0 ;[Red](#,##0)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 38, Format = "#,##0 ;[Red](#,##0)" });
161            NumberFormats.Add("#,##0.00;(#,##0.00)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 39, Format = "#,##0.00;(#,##0.00)" });
162            NumberFormats.Add("#,##0.00;[Red](#,#)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 40, Format = "#,##0.00;[Red](#,#)" });
163            NumberFormats.Add("mm:ss", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 45, Format = "mm:ss" });
164            NumberFormats.Add("[h]:mm:ss", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 46, Format = "[h]:mm:ss" });
165            NumberFormats.Add("mmss.0", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 47, Format = "mmss.0" });
166            NumberFormats.Add("##0.0", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 48, Format = "##0.0" });
167            NumberFormats.Add("@", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 49, Format = "@" });
168
169            NumberFormats.NextId = 164; //Start for custom formats.
170        }
171
172        internal override XmlNode CreateXmlNode(XmlNode topNode)
173        {
174            TopNode = topNode;
175            SetXmlNodeString("@numFmtId", NumFmtId.ToString());
176            SetXmlNodeString("@formatCode", Format);
177            return TopNode;
178        }
179
180        internal enum eFormatType
181        {
182            Unknown = 0,
183            Number = 1,
184            DateTime = 2,
185        }
186        ExcelFormatTranslator _translator = null;
187        internal ExcelFormatTranslator FormatTranslator
188        {
189            get
190            {
191                if (_translator == null)
192                {
193                    _translator = new ExcelFormatTranslator(Format, NumFmtId);
194                }
195                return _translator;
196            }
197        }
198        #region Excel --> .Net Format
199        internal class ExcelFormatTranslator
200        {
201            internal ExcelFormatTranslator(string format, int numFmtID)
202            {
203                if (numFmtID == 14)
204                {
205                    NetFormat = NetFormatForWidth = "d";
206                    NetTextFormat = NetTextFormatForWidth = "";
207                    DataType = eFormatType.DateTime;
208                }
209                else if (format.ToLower() == "general")
210                {
211                    NetFormat = NetFormatForWidth = "0.#####";
212                    NetTextFormat = NetTextFormatForWidth = "";
213                    DataType = eFormatType.Number;
214                }
215                else
216                {
217                    ToNetFormat(format, false);
218                    ToNetFormat(format, true);
219                }               
220            }
221            internal string NetTextFormat { get; private set; }
222            internal string NetFormat { get; private set; }
223            CultureInfo _ci = null;
224            internal CultureInfo Culture
225            {
226                get
227                {
228                    if (_ci == null)
229                    {
230                        return CultureInfo.CurrentCulture;
231                    }
232                    return _ci;
233                }
234                private set
235                {
236                    _ci = value;
237                }
238            }
239            internal eFormatType DataType { get; private set; }
240            internal string NetTextFormatForWidth { get; private set; }
241            internal string NetFormatForWidth { get; private set; }
242
243            //internal string FractionFormatInteger { get; private set; }
244            internal string FractionFormat { get; private set; }
245            //internal string FractionFormat2 { get; private set; }
246
247            private void ToNetFormat(string ExcelFormat, bool forColWidth)
248            {
249                DataType = eFormatType.Unknown;
250                int secCount = 0;
251                bool isText = false;
252                bool isBracket = false;
253                string bracketText = "";
254                bool prevBslsh = false;
255                bool useMinute = false;
256                bool prevUnderScore = false;
257                bool ignoreNext = false;
258                int fractionPos = -1;
259                string specialDateFormat = "";
260                bool containsAmPm = ExcelFormat.Contains("AM/PM");
261
262                StringBuilder sb = new StringBuilder();
263                Culture = null;
264                var format = "";
265                var text = "";
266                char clc;
267
268                if (containsAmPm)
269                {
270                    ExcelFormat = Regex.Replace(ExcelFormat, "AM/PM", "");
271                    DataType = eFormatType.DateTime;
272                }
273
274                for (int pos = 0; pos < ExcelFormat.Length; pos++)
275                {
276                    char c = ExcelFormat[pos];
277                    if (c == '"')
278                    {
279                        isText = !isText;
280                    }
281                    else
282                    {
283                        if (ignoreNext)
284                        {
285                            ignoreNext = false;
286                            continue;
287                        }
288                        else if (isText && !isBracket)
289                        {
290                            sb.Append(c);
291                        }
292                        else if (isBracket)
293                        {
294                            if (c == ']')
295                            {
296                                isBracket = false;
297                                if (bracketText[0] == '$')  //Local Info
298                                {
299                                    string[] li = Regex.Split(bracketText, "-");
300                                    if (li[0].Length > 1)
301                                    {
302                                        sb.Append("\"" + li[0].Substring(1, li[0].Length - 1) + "\"");     //Currency symbol
303                                    }
304                                    if (li.Length > 1)
305                                    {
306                                        if (li[1].ToLower() == "f800")
307                                        {
308                                            specialDateFormat = "D";
309                                        }
310                                        else if (li[1].ToLower() == "f400")
311                                        {
312                                            specialDateFormat = "T";
313                                        }
314                                        else
315                                        {
316                                            var num = int.Parse(li[1], NumberStyles.HexNumber);
317                                            try
318                                            {
319                                                Culture = CultureInfo.GetCultureInfo(num & 0xFFFF);
320                                            }
321                                            catch
322                                            {
323                                                Culture = null;
324                                            }
325                                        }
326                                    }
327                                }
328                            }
329                            else
330                            {
331                                bracketText += c;
332                            }
333                        }
334                        else if (prevUnderScore)
335                        {
336                            if (forColWidth)
337                            {
338                                sb.AppendFormat("\"{0}\"", c);
339                            }
340                            prevUnderScore = false;
341                        }
342                        else
343                        {
344                            if (c == ';') //We use first part (for positive only at this stage)
345                            {
346                                secCount++;
347                                if (DataType == eFormatType.DateTime || secCount == 3)
348                                {
349                                    format = sb.ToString();
350                                    sb = new StringBuilder();
351                                }
352                                else
353                                {
354                                    sb.Append(c);
355                                }
356                            }
357                            else
358                            {
359                                clc = c.ToString().ToLower()[0];  //Lowercase character
360                                //Set the datetype
361                                if (DataType == eFormatType.Unknown)
362                                {
363                                    if (c == '0' || c == '#' || c == '.')
364                                    {
365                                        DataType = eFormatType.Number;
366                                    }
367                                    else if (clc == 'y' || clc == 'm' || clc == 'd' || clc == 'h' || clc == 'm' || clc == 's')
368                                    {
369                                        DataType = eFormatType.DateTime;
370                                    }
371                                }
372
373                                if (prevBslsh)
374                                {
375                                    sb.Append(c);
376                                    prevBslsh = false;
377                                }
378                                else if (c == '[')
379                                {
380                                    bracketText = "";
381                                    isBracket = true;
382                                }
383                                else if (c == '\\')
384                                {
385                                    prevBslsh = true;
386                                }
387                                else if (c == '0' ||
388                                    c == '#' ||
389                                    c == '.' ||
390                                    c == ',' ||
391                                    c == '%' ||
392                                    clc == 'd' ||
393                                    clc == 's')
394                                {
395                                    sb.Append(c);
396                                }
397                                else if (clc == 'h')
398                                {
399                                    if (containsAmPm)
400                                    {
401                                        sb.Append('h'); ;
402                                    }
403                                    else
404                                    {
405                                        sb.Append('H');
406                                    }
407                                    useMinute = true;
408                                }
409                                else if (clc == 'm')
410                                {
411                                    if (useMinute)
412                                    {
413                                        sb.Append('m');
414                                    }
415                                    else
416                                    {
417                                        sb.Append('M');
418                                    }
419                                }
420                                else if (c == '_') //Skip next but use for alignment
421                                {
422                                    prevUnderScore = true;
423                                }
424                                else if (c == '?')
425                                {
426                                    sb.Append(' ');
427                                }
428                                else if (c == '/')
429                                {
430                                    if (DataType == eFormatType.Number)
431                                    {
432                                        fractionPos = sb.Length;
433                                        int startPos = pos - 1;
434                                        while (startPos >= 0 &&
435                                                (ExcelFormat[startPos] == '?' ||
436                                                ExcelFormat[startPos] == '#' ||
437                                                ExcelFormat[startPos] == '0'))
438                                        {
439                                            startPos--;
440                                        }
441
442                                        if (startPos > 0)  //RemovePart
443                                            sb.Remove(sb.Length-(pos-startPos-1),(pos-startPos-1)) ;
444
445                                        int endPos = pos + 1;
446                                        while (endPos < ExcelFormat.Length &&
447                                                (ExcelFormat[endPos] == '?' ||
448                                                ExcelFormat[endPos] == '#' ||
449                                                (ExcelFormat[endPos] >= '0' && ExcelFormat[endPos]<= '9')))
450                                        {
451                                            endPos++;
452                                        }
453                                        pos = endPos;
454                                        if (FractionFormat != "")
455                                        {
456                                            FractionFormat = ExcelFormat.Substring(startPos+1, endPos - startPos-1);
457                                        }
458                                        sb.Append('?'); //Will be replaced later on by the fraction
459                                    }
460                                    else
461                                    {
462                                        sb.Append('/');
463                                    }
464                                }
465                                else if (c == '*')
466                                {
467                                    //repeat char--> ignore
468                                    ignoreNext = true;
469                                }
470                                else if (c == '@')
471                                {
472                                    sb.Append("{0}");
473                                }
474                                else
475                                {
476                                    sb.Append(c);
477                                }
478                            }
479                        }
480                    }
481                }
482
483                // AM/PM format
484                if (containsAmPm)
485                {
486                    format += "tt";
487                }
488
489
490                if (format == "")
491                    format = sb.ToString();
492                else
493                    text = sb.ToString();
494                if (specialDateFormat != "")
495                {
496                    format = specialDateFormat;
497                }
498
499                if (forColWidth)
500                {
501                    NetFormatForWidth = format;
502                    NetTextFormatForWidth = text;
503                }
504                else
505                {
506                    NetFormat = format;
507                    NetTextFormat = text;
508                }
509                if (Culture == null)
510                {
511                    Culture = CultureInfo.CurrentCulture;
512                }
513            }
514            internal string FormatFraction(double d)
515            {
516                int numerator, denomerator;
517
518                int intPart = (int)d;
519
520                string[] fmt = FractionFormat.Split('/');
521
522                int fixedDenominator;
523                if (!int.TryParse(fmt[1], out fixedDenominator))
524                {
525                    fixedDenominator = 0;
526                }
527               
528                if (d == 0 || double.IsNaN(d))
529                {
530                    if (fmt[0].Trim() == "" && fmt[1].Trim() == "")
531                    {
532                        return new string(' ', FractionFormat.Length);
533                    }
534                    else
535                    {
536                        return 0.ToString(fmt[0]) + "/" + 1.ToString(fmt[0]);
537                    }
538                }
539
540                int maxDigits = fmt[1].Length;
541                string sign = d < 0 ? "-" : "";
542                if (fixedDenominator == 0)
543                {
544                    List<double> numerators = new List<double>() { 1, 0 };
545                    List<double> denominators = new List<double>() { 0, 1 };
546
547                    if (maxDigits < 1 && maxDigits > 12)
548                    {
549                        throw (new ArgumentException("Number of digits out of range (1-12)"));
550                    }
551
552                    int maxNum = 0;
553                    for (int i = 0; i < maxDigits; i++)
554                    {
555                        maxNum += 9 * (int)(Math.Pow((double)10, (double)i));
556                    }
557
558                    double divRes = 1 / ((double)Math.Abs(d) - intPart);
559                    double result, prevResult = double.NaN;
560                    int listPos = 2, index = 1;
561                    while (true)
562                    {
563                        index++;
564                        double intDivRes = Math.Floor(divRes);
565                        numerators.Add((intDivRes * numerators[index - 1] + numerators[index - 2]));
566                        if (numerators[index] > maxNum)
567                        {
568                            break;
569                        }
570
571                        denominators.Add((intDivRes * denominators[index - 1] + denominators[index - 2]));
572
573                        result = numerators[index] / denominators[index];
574                        if (denominators[index] > maxNum)
575                        {
576                            break;
577                        }
578                        listPos = index;
579
580                        if (result == prevResult) break;
581
582                        if (result == d) break;
583
584                        prevResult = result;
585
586                        divRes = 1 / (divRes - intDivRes);  //Rest
587                    }
588                   
589                    numerator = (int)numerators[listPos];
590                    denomerator = (int)denominators[listPos];
591                }
592                else
593                {
594                    numerator = (int)Math.Round((d - intPart) / (1D / fixedDenominator), 0);
595                    denomerator = fixedDenominator;
596                }
597                if (numerator == denomerator || numerator==0)
598                {
599                    if(numerator == denomerator) intPart++;
600                    return sign + intPart.ToString(NetFormat).Replace("?", new string(' ', FractionFormat.Length));
601                }
602                else if (intPart == 0)
603                {
604                    return sign + FmtInt(numerator, fmt[0]) + "/" + FmtInt(denomerator, fmt[1]);
605                }
606                else
607                {
608                    return sign + intPart.ToString(NetFormat).Replace("?", FmtInt(numerator, fmt[0]) + "/" + FmtInt(denomerator, fmt[1]));
609                }
610            }
611
612            private string FmtInt(double value, string format)
613            {
614                string v = value.ToString("#");
615                string pad = "";
616                if (v.Length < format.Length)
617                {
618                    for (int i = format.Length - v.Length-1; i >= 0; i--)
619                    {
620                        if (format[i] == '?')
621                        {
622                            pad += " ";
623                        }
624                        else if (format[i] == ' ')
625                        {
626                            pad += "0";
627                        }
628                    }
629                }
630                return pad + v;
631            }
632        }
633        #endregion
634    }
635}
Note: See TracBrowser for help on using the repository browser.