| /******************************************************************************* | 
 |  * You may amend and distribute as you like, but don't remove this header! | 
 |  * | 
 |  * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets. | 
 |  * See http://www.codeplex.com/EPPlus for details. | 
 |  * | 
 |  * Copyright (C) 2011  Jan Källman | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Lesser General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2.1 of the License, or (at your option) any later version. | 
 |  | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   | 
 |  * See the GNU Lesser General Public License for more details. | 
 |  * | 
 |  * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php | 
 |  * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html | 
 |  * | 
 |  * All code and executables are provided "as is" with no warranty either express or implied.  | 
 |  * The author accepts no liability for any damage or loss of business that this product may cause. | 
 |  * | 
 |  * Code change notes: | 
 |  *  | 
 |  * Author							Change						Date | 
 |  * ****************************************************************************** | 
 |  * Jan Källman		                Initial Release		        2009-10-01 | 
 |  * Jan Källman		License changed GPL-->LGPL 2011-12-16 | 
 |  *******************************************************************************/ | 
 | using System; | 
 | using System.Collections.Generic; | 
 | using System.Text; | 
 | using System.Xml; | 
 | using System.Globalization; | 
 | using System.Text.RegularExpressions; | 
 | namespace OfficeOpenXml.Style.XmlAccess | 
 | { | 
 |     /// <summary> | 
 |     /// Xml access class for number formats | 
 |     /// </summary> | 
 |     public sealed class ExcelNumberFormatXml : StyleXmlHelper | 
 |     { | 
 |         internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager) : base(nameSpaceManager) | 
 |         { | 
 |              | 
 |         }         | 
 |         internal ExcelNumberFormatXml(XmlNamespaceManager nameSpaceManager, bool buildIn): base(nameSpaceManager) | 
 |         { | 
 |             BuildIn = buildIn; | 
 |         } | 
 |         internal ExcelNumberFormatXml(XmlNamespaceManager nsm, XmlNode topNode) : | 
 |             base(nsm, topNode) | 
 |         { | 
 |             _numFmtId = GetXmlNodeInt("@numFmtId"); | 
 |             _format = GetXmlNodeString("@formatCode"); | 
 |         } | 
 |         public bool BuildIn { get; private set; } | 
 |         int _numFmtId; | 
 | //        const string idPath = "@numFmtId"; | 
 |         /// <summary> | 
 |         /// Id for number format | 
 |         ///  | 
 |         /// Build in ID's | 
 |         ///  | 
 |         /// 0   General  | 
 |         /// 1   0  | 
 |         /// 2   0.00  | 
 |         /// 3   #,##0  | 
 |         /// 4   #,##0.00  | 
 |         /// 9   0%  | 
 |         /// 10  0.00%  | 
 |         /// 11  0.00E+00  | 
 |         /// 12  # ?/?  | 
 |         /// 13  # ??/??  | 
 |         /// 14  mm-dd-yy  | 
 |         /// 15  d-mmm-yy  | 
 |         /// 16  d-mmm  | 
 |         /// 17  mmm-yy  | 
 |         /// 18  h:mm AM/PM  | 
 |         /// 19  h:mm:ss AM/PM  | 
 |         /// 20  h:mm  | 
 |         /// 21  h:mm:ss  | 
 |         /// 22  m/d/yy h:mm  | 
 |         /// 37  #,##0 ;(#,##0)  | 
 |         /// 38  #,##0 ;[Red](#,##0)  | 
 |         /// 39  #,##0.00;(#,##0.00)  | 
 |         /// 40  #,##0.00;[Red](#,##0.00)  | 
 |         /// 45  mm:ss  | 
 |         /// 46  [h]:mm:ss  | 
 |         /// 47  mmss.0  | 
 |         /// 48  ##0.0E+0  | 
 |         /// 49  @ | 
 |         /// </summary>             | 
 |         public int NumFmtId | 
 |         { | 
 |             get | 
 |             { | 
 |                 return _numFmtId; | 
 |             } | 
 |             set | 
 |             { | 
 |                 _numFmtId = value; | 
 |             } | 
 |         } | 
 |         internal override string Id | 
 |         { | 
 |             get | 
 |             { | 
 |                 return _format; | 
 |             } | 
 |         } | 
 |         const string fmtPath = "@formatCode"; | 
 |         string _format = string.Empty; | 
 |         public string Format | 
 |         { | 
 |             get | 
 |             { | 
 |                 return _format; | 
 |             } | 
 |             set | 
 |             { | 
 |                 _numFmtId = ExcelNumberFormat.GetFromBuildIdFromFormat(value); | 
 |                 _format = value; | 
 |             } | 
 |         } | 
 |         internal string GetNewID(int NumFmtId, string Format) | 
 |         { | 
 |              | 
 |             if (NumFmtId < 0) | 
 |             { | 
 |                 NumFmtId = ExcelNumberFormat.GetFromBuildIdFromFormat(Format);                 | 
 |             } | 
 |             return NumFmtId.ToString(); | 
 |         } | 
 |  | 
 |         internal static void AddBuildIn(XmlNamespaceManager NameSpaceManager, ExcelStyleCollection<ExcelNumberFormatXml> NumberFormats) | 
 |         { | 
 |             NumberFormats.Add("General",new ExcelNumberFormatXml(NameSpaceManager,true){NumFmtId=0,Format="General"}); | 
 |             NumberFormats.Add("0", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 1, Format = "0" }); | 
 |             NumberFormats.Add("0.00", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 2, Format = "0.00" }); | 
 |             NumberFormats.Add("#,##0", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 3, Format = "#,##0" }); | 
 |             NumberFormats.Add("#,##0.00", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 4, Format = "#,##0.00" }); | 
 |             NumberFormats.Add("0%", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 9, Format = "0%" }); | 
 |             NumberFormats.Add("0.00%", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 10, Format = "0.00%" }); | 
 |             NumberFormats.Add("0.00E+00", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 11, Format = "0.00E+00" }); | 
 |             NumberFormats.Add("# ?/?", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 12, Format = "# ?/?" }); | 
 |             NumberFormats.Add("# ??/??", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 13, Format = "# ??/??" }); | 
 |             NumberFormats.Add("mm-dd-yy", new ExcelNumberFormatXml(NameSpaceManager,true) { NumFmtId = 14, Format = "mm-dd-yy" }); | 
 |             NumberFormats.Add("d-mmm-yy", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 15, Format = "d-mmm-yy" }); | 
 |             NumberFormats.Add("d-mmm", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 16, Format = "d-mmm" }); | 
 |             NumberFormats.Add("mmm-yy", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 17, Format = "mmm-yy" }); | 
 |             NumberFormats.Add("h:mm AM/PM", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 18, Format = "h:mm AM/PM" }); | 
 |             NumberFormats.Add("h:mm:ss AM/PM", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 19, Format = "h:mm:ss AM/PM" }); | 
 |             NumberFormats.Add("h:mm", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 20, Format = "h:mm" }); | 
 |             NumberFormats.Add("h:mm:ss", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 21, Format = "h:mm:ss" }); | 
 |             NumberFormats.Add("m/d/yy h:mm", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 22, Format = "m/d/yy h:mm" }); | 
 |             NumberFormats.Add("#,##0 ;(#,##0)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 37, Format = "#,##0 ;(#,##0)" }); | 
 |             NumberFormats.Add("#,##0 ;[Red](#,##0)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 38, Format = "#,##0 ;[Red](#,##0)" }); | 
 |             NumberFormats.Add("#,##0.00;(#,##0.00)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 39, Format = "#,##0.00;(#,##0.00)" }); | 
 |             NumberFormats.Add("#,##0.00;[Red](#,##0.00)", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 40, Format = "#,##0.00;[Red](#,#)" }); | 
 |             NumberFormats.Add("mm:ss", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 45, Format = "mm:ss" }); | 
 |             NumberFormats.Add("[h]:mm:ss", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 46, Format = "[h]:mm:ss" }); | 
 |             NumberFormats.Add("mmss.0", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 47, Format = "mmss.0" }); | 
 |             NumberFormats.Add("##0.0", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 48, Format = "##0.0" }); | 
 |             NumberFormats.Add("@", new ExcelNumberFormatXml(NameSpaceManager, true) { NumFmtId = 49, Format = "@" }); | 
 |  | 
 |             NumberFormats.NextId = 164; //Start for custom formats. | 
 |         } | 
 |  | 
 |         internal override XmlNode CreateXmlNode(XmlNode topNode) | 
 |         { | 
 |             TopNode = topNode; | 
 |             SetXmlNodeString("@numFmtId", NumFmtId.ToString()); | 
 |             SetXmlNodeString("@formatCode", Format); | 
 |             return TopNode; | 
 |         } | 
 |  | 
 |         internal enum eFormatType | 
 |         { | 
 |             Unknown = 0, | 
 |             Number = 1, | 
 |             DateTime = 2, | 
 |         } | 
 |         ExcelFormatTranslator _translator = null; | 
 |         internal ExcelFormatTranslator FormatTranslator | 
 |         { | 
 |             get | 
 |             { | 
 |                 if (_translator == null) | 
 |                 { | 
 |                     _translator = new ExcelFormatTranslator(Format, NumFmtId); | 
 |                 } | 
 |                 return _translator; | 
 |             } | 
 |         } | 
 |         #region Excel --> .Net Format | 
 |         internal class ExcelFormatTranslator | 
 |         { | 
 |             internal ExcelFormatTranslator(string format, int numFmtID) | 
 |             { | 
 |                 if (numFmtID == 14) | 
 |                 { | 
 |                     NetFormat = NetFormatForWidth = "d"; | 
 |                     NetTextFormat = NetTextFormatForWidth = ""; | 
 |                     DataType = eFormatType.DateTime; | 
 |                 } | 
 |                 else if (format.Equals("general",StringComparison.InvariantCultureIgnoreCase)) | 
 |                 { | 
 |                     NetFormat = NetFormatForWidth = "0.#####"; | 
 |                     NetTextFormat = NetTextFormatForWidth = ""; | 
 |                     DataType = eFormatType.Number; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     ToNetFormat(format, false); | 
 |                     ToNetFormat(format, true); | 
 |                 }                 | 
 |             } | 
 |             internal string NetTextFormat { get; private set; } | 
 |             internal string NetFormat { get; private set; } | 
 |             CultureInfo _ci = null; | 
 |             internal CultureInfo Culture | 
 |             { | 
 |                 get | 
 |                 { | 
 |                     if (_ci == null) | 
 |                     { | 
 |                         return CultureInfo.CurrentCulture; | 
 |                     } | 
 |                     return _ci; | 
 |                 } | 
 |                 private set | 
 |                 { | 
 |                     _ci = value; | 
 |                 } | 
 |             } | 
 |             internal eFormatType DataType { get; private set; } | 
 |             internal string NetTextFormatForWidth { get; private set; } | 
 |             internal string NetFormatForWidth { get; private set; } | 
 |  | 
 |             //internal string FractionFormatInteger { get; private set; } | 
 |             internal string FractionFormat { get; private set; } | 
 |             //internal string FractionFormat2 { get; private set; } | 
 |  | 
 |             private void ToNetFormat(string ExcelFormat, bool forColWidth) | 
 |             { | 
 |                 DataType = eFormatType.Unknown; | 
 |                 int secCount = 0; | 
 |                 bool isText = false; | 
 |                 bool isBracket = false; | 
 |                 string bracketText = ""; | 
 |                 bool prevBslsh = false; | 
 |                 bool useMinute = false; | 
 |                 bool prevUnderScore = false; | 
 |                 bool ignoreNext = false; | 
 |                 int fractionPos = -1; | 
 |                 string specialDateFormat = ""; | 
 |                 bool containsAmPm = ExcelFormat.Contains("AM/PM"); | 
 |                 List<int> lstDec=new List<int>(); | 
 |                 StringBuilder sb = new StringBuilder(); | 
 |                 Culture = null; | 
 |                 var format = ""; | 
 |                 var text = ""; | 
 |                 char clc; | 
 |  | 
 |                 if (containsAmPm) | 
 |                 { | 
 |                     ExcelFormat = Regex.Replace(ExcelFormat, "AM/PM", ""); | 
 |                     DataType = eFormatType.DateTime; | 
 |                 } | 
 |  | 
 |                 for (int pos = 0; pos < ExcelFormat.Length; pos++) | 
 |                 { | 
 |                     char c = ExcelFormat[pos]; | 
 |                     if (c == '"') | 
 |                     { | 
 |                         isText = !isText; | 
 |                     } | 
 |                     else | 
 |                     { | 
 |                         if (ignoreNext) | 
 |                         { | 
 |                             ignoreNext = false; | 
 |                             continue; | 
 |                         } | 
 |                         else if (isText && !isBracket) | 
 |                         { | 
 |                             sb.Append(c); | 
 |                         } | 
 |                         else if (isBracket) | 
 |                         { | 
 |                             if (c == ']') | 
 |                             { | 
 |                                 isBracket = false; | 
 |                                 if (bracketText[0] == '$')  //Local Info | 
 |                                 { | 
 |                                     string[] li = Regex.Split(bracketText, "-"); | 
 |                                     if (li[0].Length > 1) | 
 |                                     { | 
 |                                         sb.Append("\"" + li[0].Substring(1, li[0].Length - 1) + "\"");     //Currency symbol | 
 |                                     } | 
 |                                     if (li.Length > 1) | 
 |                                     { | 
 |                                         if (li[1].Equals("f800", StringComparison.InvariantCultureIgnoreCase)) | 
 |                                         { | 
 |                                             specialDateFormat = "D"; | 
 |                                         } | 
 |                                         else if (li[1].Equals("f400", StringComparison.InvariantCultureIgnoreCase)) | 
 |                                         { | 
 |                                             specialDateFormat = "T"; | 
 |                                         } | 
 |                                         else | 
 |                                         { | 
 |                                             var num = int.Parse(li[1], NumberStyles.HexNumber); | 
 |                                             try | 
 |                                             { | 
 |                                                 Culture = CultureInfo.GetCultureInfo(num & 0xFFFF); | 
 |                                             } | 
 |                                             catch | 
 |                                             { | 
 |                                                 Culture = null; | 
 |                                             } | 
 |                                         } | 
 |                                     } | 
 |                                 } | 
 |                                 else if(bracketText[0]=='t') | 
 |                                 { | 
 |                                     sb.Append("hh"); //TODO:This will not be correct for dates over 24H. | 
 |                                 } | 
 |                                 else if (bracketText[0] == 'h') | 
 |                                 { | 
 |                                     specialDateFormat = "hh"; //TODO:This will not be correct for dates over 24H. | 
 |                                 } | 
 |                             } | 
 |                             else | 
 |                             { | 
 |                                 bracketText += c; | 
 |                             } | 
 |                         } | 
 |                         else if (prevUnderScore) | 
 |                         { | 
 |                             if (forColWidth) | 
 |                             { | 
 |                                 sb.AppendFormat("\"{0}\"", c); | 
 |                             } | 
 |                             prevUnderScore = false; | 
 |                         } | 
 |                         else | 
 |                         { | 
 |                             if (c == ';') //We use first part (for positive only at this stage) | 
 |                             { | 
 |                                 secCount++; | 
 |                                 if (DataType == eFormatType.DateTime || secCount == 3) | 
 |                                 { | 
 |                                     //Add qoutes | 
 |                                     if (DataType == eFormatType.DateTime) SetDecimal(lstDec, sb); //Remove? | 
 |                                     lstDec = new List<int>(); | 
 |                                     format = sb.ToString(); | 
 |                                     sb = new StringBuilder(); | 
 |                                 } | 
 |                                 else | 
 |                                 { | 
 |                                     sb.Append(c); | 
 |                                 } | 
 |                             } | 
 |                             else | 
 |                             { | 
 |                                 clc = c.ToString().ToLower(CultureInfo.InvariantCulture)[0];  //Lowercase character | 
 |                                 //Set the datetype | 
 |                                 if (DataType == eFormatType.Unknown) | 
 |                                 { | 
 |                                     if (c == '0' || c == '#' || c == '.') | 
 |                                     { | 
 |                                         DataType = eFormatType.Number; | 
 |                                     } | 
 |                                     else if (clc == 'y' || clc == 'm' || clc == 'd' || clc == 'h' || clc == 'm' || clc == 's') | 
 |                                     { | 
 |                                         DataType = eFormatType.DateTime; | 
 |                                     } | 
 |                                 } | 
 |  | 
 |                                 if (prevBslsh) | 
 |                                 { | 
 |                                     if (c == '.' || c == ',') | 
 |                                     { | 
 |                                         sb.Append('\\'); | 
 |                                     }                                     | 
 |                                     sb.Append(c); | 
 |                                     prevBslsh = false; | 
 |                                 } | 
 |                                 else if (c == '[') | 
 |                                 { | 
 |                                     bracketText = ""; | 
 |                                     isBracket = true; | 
 |                                 } | 
 |                                 else if (c == '\\') | 
 |                                 { | 
 |                                     prevBslsh = true; | 
 |                                 } | 
 |                                 else if (c == '0' || | 
 |                                     c == '#' || | 
 |                                     c == '.' || | 
 |                                     c == ',' || | 
 |                                     c == '%' || | 
 |                                     clc == 'd' || | 
 |                                     clc == 's') | 
 |                                 { | 
 |                                     sb.Append(c); | 
 |                                     if(c=='.') | 
 |                                     { | 
 |                                         lstDec.Add(sb.Length - 1); | 
 |                                     } | 
 |                                 } | 
 |                                 else if (clc == 'h') | 
 |                                 { | 
 |                                     if (containsAmPm) | 
 |                                     { | 
 |                                         sb.Append('h'); ; | 
 |                                     } | 
 |                                     else | 
 |                                     { | 
 |                                         sb.Append('H'); | 
 |                                     } | 
 |                                     useMinute = true; | 
 |                                 } | 
 |                                 else if (clc == 'm') | 
 |                                 { | 
 |                                     if (useMinute) | 
 |                                     { | 
 |                                         sb.Append('m'); | 
 |                                     } | 
 |                                     else | 
 |                                     { | 
 |                                         sb.Append('M'); | 
 |                                     } | 
 |                                 } | 
 |                                 else if (c == '_') //Skip next but use for alignment | 
 |                                 { | 
 |                                     prevUnderScore = true; | 
 |                                 } | 
 |                                 else if (c == '?') | 
 |                                 { | 
 |                                     sb.Append(' '); | 
 |                                 } | 
 |                                 else if (c == '/') | 
 |                                 { | 
 |                                     if (DataType == eFormatType.Number) | 
 |                                     { | 
 |                                         fractionPos = sb.Length; | 
 |                                         int startPos = pos - 1; | 
 |                                         while (startPos >= 0 && | 
 |                                                 (ExcelFormat[startPos] == '?' || | 
 |                                                 ExcelFormat[startPos] == '#' || | 
 |                                                 ExcelFormat[startPos] == '0')) | 
 |                                         { | 
 |                                             startPos--; | 
 |                                         } | 
 |  | 
 |                                         if (startPos > 0)  //RemovePart | 
 |                                             sb.Remove(sb.Length-(pos-startPos-1),(pos-startPos-1)) ; | 
 |  | 
 |                                         int endPos = pos + 1; | 
 |                                         while (endPos < ExcelFormat.Length && | 
 |                                                 (ExcelFormat[endPos] == '?' || | 
 |                                                 ExcelFormat[endPos] == '#' || | 
 |                                                 (ExcelFormat[endPos] >= '0' && ExcelFormat[endPos]<= '9'))) | 
 |                                         { | 
 |                                             endPos++; | 
 |                                         } | 
 |                                         pos = endPos; | 
 |                                         if (FractionFormat != "") | 
 |                                         { | 
 |                                             FractionFormat = ExcelFormat.Substring(startPos+1, endPos - startPos-1); | 
 |                                         } | 
 |                                         sb.Append('?'); //Will be replaced later on by the fraction | 
 |                                     } | 
 |                                     else | 
 |                                     { | 
 |                                         sb.Append('/'); | 
 |                                     } | 
 |                                 } | 
 |                                 else if (c == '*') | 
 |                                 { | 
 |                                     //repeat char--> ignore | 
 |                                     ignoreNext = true; | 
 |                                 } | 
 |                                 else if (c == '@') | 
 |                                 { | 
 |                                     sb.Append("{0}"); | 
 |                                 } | 
 |                                 else | 
 |                                 { | 
 |                                     sb.Append(c); | 
 |                                 } | 
 |                             } | 
 |                         } | 
 |                     } | 
 |                 } | 
 |  | 
 |                 //Add qoutes | 
 |                 if (DataType == eFormatType.DateTime) SetDecimal(lstDec, sb); //Remove? | 
 |  | 
 |                 // AM/PM format | 
 |                 if (containsAmPm) | 
 |                 { | 
 |                     format += "tt"; | 
 |                 } | 
 |  | 
 |  | 
 |                 if (format == "") | 
 |                     format = sb.ToString(); | 
 |                 else | 
 |                     text = sb.ToString(); | 
 |                 if (specialDateFormat != "") | 
 |                 { | 
 |                     format = specialDateFormat; | 
 |                 } | 
 |  | 
 |                 if (forColWidth) | 
 |                 { | 
 |                     NetFormatForWidth = format; | 
 |                     NetTextFormatForWidth = text; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     NetFormat = format; | 
 |                     NetTextFormat = text; | 
 |                 } | 
 |                 if (Culture == null) | 
 |                 { | 
 |                     Culture = CultureInfo.CurrentCulture; | 
 |                 } | 
 |             } | 
 |  | 
 |             private static void SetDecimal(List<int> lstDec, StringBuilder sb) | 
 |             { | 
 |                 if (lstDec.Count > 1) | 
 |                 { | 
 |                     for (int i = lstDec.Count - 1; i >= 0; i--) | 
 |                     { | 
 |                         sb.Insert(lstDec[i] + 1, '\''); | 
 |                         sb.Insert(lstDec[i], '\''); | 
 |                     } | 
 |                 } | 
 |             } | 
 |  | 
 |             internal string FormatFraction(double d) | 
 |             { | 
 |                 int numerator, denomerator; | 
 |  | 
 |                 int intPart = (int)d; | 
 |  | 
 |                 string[] fmt = FractionFormat.Split('/'); | 
 |  | 
 |                 int fixedDenominator; | 
 |                 if (!int.TryParse(fmt[1], out fixedDenominator)) | 
 |                 { | 
 |                     fixedDenominator = 0; | 
 |                 } | 
 |                  | 
 |                 if (d == 0 || double.IsNaN(d)) | 
 |                 { | 
 |                     if (fmt[0].Trim() == "" && fmt[1].Trim() == "") | 
 |                     { | 
 |                         return new string(' ', FractionFormat.Length); | 
 |                     } | 
 |                     else | 
 |                     { | 
 |                         return 0.ToString(fmt[0]) + "/" + 1.ToString(fmt[0]); | 
 |                     } | 
 |                 } | 
 |  | 
 |                 int maxDigits = fmt[1].Length; | 
 |                 string sign = d < 0 ? "-" : ""; | 
 |                 if (fixedDenominator == 0) | 
 |                 { | 
 |                     List<double> numerators = new List<double>() { 1, 0 }; | 
 |                     List<double> denominators = new List<double>() { 0, 1 }; | 
 |  | 
 |                     if (maxDigits < 1 && maxDigits > 12) | 
 |                     { | 
 |                         throw (new ArgumentException("Number of digits out of range (1-12)")); | 
 |                     } | 
 |  | 
 |                     int maxNum = 0; | 
 |                     for (int i = 0; i < maxDigits; i++) | 
 |                     { | 
 |                         maxNum += 9 * (int)(Math.Pow((double)10, (double)i)); | 
 |                     } | 
 |  | 
 |                     double divRes = 1 / ((double)Math.Abs(d) - intPart); | 
 |                     double result, prevResult = double.NaN; | 
 |                     int listPos = 2, index = 1; | 
 |                     while (true) | 
 |                     { | 
 |                         index++; | 
 |                         double intDivRes = Math.Floor(divRes); | 
 |                         numerators.Add((intDivRes * numerators[index - 1] + numerators[index - 2])); | 
 |                         if (numerators[index] > maxNum) | 
 |                         { | 
 |                             break; | 
 |                         } | 
 |  | 
 |                         denominators.Add((intDivRes * denominators[index - 1] + denominators[index - 2])); | 
 |  | 
 |                         result = numerators[index] / denominators[index]; | 
 |                         if (denominators[index] > maxNum) | 
 |                         { | 
 |                             break; | 
 |                         } | 
 |                         listPos = index; | 
 |  | 
 |                         if (result == prevResult) break; | 
 |  | 
 |                         if (result == d) break; | 
 |  | 
 |                         prevResult = result; | 
 |  | 
 |                         divRes = 1 / (divRes - intDivRes);  //Rest | 
 |                     } | 
 |                      | 
 |                     numerator = (int)numerators[listPos]; | 
 |                     denomerator = (int)denominators[listPos]; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     numerator = (int)Math.Round((d - intPart) / (1D / fixedDenominator), 0); | 
 |                     denomerator = fixedDenominator; | 
 |                 } | 
 |                 if (numerator == denomerator || numerator==0) | 
 |                 { | 
 |                     if(numerator == denomerator) intPart++; | 
 |                     return sign + intPart.ToString(NetFormat).Replace("?", new string(' ', FractionFormat.Length)); | 
 |                 } | 
 |                 else if (intPart == 0) | 
 |                 { | 
 |                     return sign + FmtInt(numerator, fmt[0]) + "/" + FmtInt(denomerator, fmt[1]); | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     return sign + intPart.ToString(NetFormat).Replace("?", FmtInt(numerator, fmt[0]) + "/" + FmtInt(denomerator, fmt[1])); | 
 |                 } | 
 |             } | 
 |  | 
 |             private string FmtInt(double value, string format) | 
 |             { | 
 |                 string v = value.ToString("#"); | 
 |                 string pad = ""; | 
 |                 if (v.Length < format.Length) | 
 |                 { | 
 |                     for (int i = format.Length - v.Length-1; i >= 0; i--) | 
 |                     { | 
 |                         if (format[i] == '?') | 
 |                         { | 
 |                             pad += " "; | 
 |                         } | 
 |                         else if (format[i] == ' ') | 
 |                         { | 
 |                             pad += "0"; | 
 |                         } | 
 |                     } | 
 |                 } | 
 |                 return pad + v; | 
 |             } | 
 |         } | 
 |         #endregion | 
 |     } | 
 | } |