/* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for Additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ namespace HH.WMS.Utils.NPOI.SS.Format { using System; using System.Text; using System.Collections.Generic; using System.Text.RegularExpressions; /** * This class : printing out an elapsed time format. * * @author Ken Arnold, Industrious Media LLC */ public class CellElapsedFormatter : CellFormatter { private List specs; private TimeSpec topmost; private String printfFmt; private static Regex PERCENTS = new Regex("%"); private static double HOUR__FACTOR = 1.0 / 24.0; private static double MIN__FACTOR = HOUR__FACTOR / 60.0; private static double SEC__FACTOR = MIN__FACTOR / 60.0; private class TimeSpec { internal char type; internal int pos; internal int len; internal double factor; internal double modBy; public TimeSpec(char type, int pos, int len, double factor) { this.type = type; this.pos = pos; this.len = len; this.factor = factor; modBy = 0; } public long ValueFor(double elapsed) { double val; if (modBy == 0) val = elapsed / factor; else val = elapsed / factor % modBy; if (type == '0') return (long)Math.Round(val); else return (long)val; } } private class ElapsedPartHandler : CellFormatPart.IPartHandler { public ElapsedPartHandler(CellElapsedFormatter formatter) { this._formatter = formatter; } // This is the one class that's directly using printf, so it can't use // the default handling for quoted strings and special characters. The // only special character for this is '%', so we have to handle all the // quoting in this method ourselves. private CellElapsedFormatter _formatter; public String HandlePart(Match m, String part, CellFormatType type, StringBuilder desc) { int pos = desc.Length; char firstCh = part[0]; switch (firstCh) { case '[': if (part.Length < 3) break; if (_formatter.topmost != null) throw new ArgumentException( "Duplicate '[' times in format"); part = part.ToLower(); int specLen = part.Length - 2; _formatter.topmost = _formatter.AssignSpec(part[1], pos, specLen); return part.Substring(1, specLen); case 'h': case 'm': case 's': case '0': part = part.ToLower(); _formatter.AssignSpec(part[0], pos, part.Length); return part; case '\n': return "%n"; case '\"': part = part.Substring(1, part.Length - 2); break; case '\\': part = part.Substring(1); break; case '*': if (part.Length > 1) part = CellFormatPart.ExpandChar(part); break; // An escape we can let it handle because it can't have a '%' case '_': return null; } // Replace ever "%" with a "%%" so we can use printf //return PERCENTS.Matcher(part).ReplaceAll("%%"); //return PERCENTS.Replace(part, "%%"); return part; } } /** * Creates a elapsed time formatter. * * @param pattern The pattern to Parse. */ public CellElapsedFormatter(String pattern) : base(pattern) { specs = new List(); StringBuilder desc = CellFormatPart.ParseFormat(pattern, CellFormatType.ELAPSED, new ElapsedPartHandler(this)); //ListIterator it = specs.ListIterator(specs.Count); //while (it.HasPrevious()) for(int i=specs.Count-1;i>=0;i--) { //TimeSpec spec = it.Previous(); TimeSpec spec = specs[i]; //desc.Replace(spec.pos, spec.pos + spec.len, "%0" + spec.len + "d"); desc.Remove(spec.pos, spec.len); desc.Insert(spec.pos, "D" + spec.len); if (spec.type != topmost.type) { spec.modBy = modFor(spec.type, spec.len); } } printfFmt = desc.ToString(); } private TimeSpec AssignSpec(char type, int pos, int len) { TimeSpec spec = new TimeSpec(type, pos, len, factorFor(type, len)); specs.Add(spec); return spec; } private static double factorFor(char type, int len) { switch (type) { case 'h': return HOUR__FACTOR; case 'm': return MIN__FACTOR; case 's': return SEC__FACTOR; case '0': return SEC__FACTOR / Math.Pow(10, len); default: throw new ArgumentException( "Uknown elapsed time spec: " + type); } } private static double modFor(char type, int len) { switch (type) { case 'h': return 24; case 'm': return 60; case 's': return 60; case '0': return Math.Pow(10, len); default: throw new ArgumentException( "Uknown elapsed time spec: " + type); } } /** {@inheritDoc} */ public override void FormatValue(StringBuilder toAppendTo, Object value) { double elapsed = ((double)value); if (elapsed < 0) { toAppendTo.Append('-'); elapsed = -elapsed; } long[] parts = new long[specs.Count]; for (int i = 0; i < specs.Count; i++) { parts[i] = specs[(i)].ValueFor(elapsed); } //Formatter formatter = new Formatter(toAppendTo); //formatter.Format(printfFmt, parts); string[] fmtPart = printfFmt.Split(":. []".ToCharArray()); string split = string.Empty; int pos = 0; int index = 0; Regex regFmt = new Regex("D\\d+"); foreach (string fmt in fmtPart) { pos += fmt.Length; if (pos < printfFmt.Length) { split = printfFmt[pos].ToString(); pos++; } else split = string.Empty; if (regFmt.IsMatch(fmt)) { toAppendTo.Append(parts[index].ToString(fmt)).Append(split); index++; } else { toAppendTo.Append(fmt).Append(split); } } //throw new NotImplementedException(); } /** * {@inheritDoc} *

* For a date, this is "mm/d/y". */ public override void SimpleValue(StringBuilder toAppendTo, Object value) { FormatValue(toAppendTo, value); } } }