/** * Returns a version of the original string that has any special characters * quoted (or escaped) as appropriate for the cell format type. The format * type object is queried to see what is special. * * @param repl The original string. * @param type The format type representation object. * * @return A version of the string with any special characters Replaced. * * @see CellFormatType#isSpecial(char) */ static String QuoteSpecial(String repl, CellFormatType type) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < repl.Length; i++) { char ch = repl[i]; if (ch == '\'' && type.IsSpecial('\'')) { sb.Append('\u0000'); continue; } bool special = type.IsSpecial(ch); if (special) { sb.Append("'"); } sb.Append(ch); if (special) { sb.Append("'"); } } return(sb.ToString()); }
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); }
public string HandlePart(Match m, string part, CellFormatType type, StringBuilder desc) { if (part.Equals("@")) { numplace++; return("\u0000"); } return(null); }
/** * Create an object to represent a format part. * * @param desc The string to Parse. */ public CellFormatPart(String desc) { Match m = FORMAT_PAT.Match(desc); if (!m.Success) { throw new ArgumentException("Unrecognized format: " + "\"" + desc + "\""); } color = GetColor(m); condition = GetCondition(m); type = GetCellFormatType(m); format = GetFormatter(m); }
public string HandlePart(Match m, string part, CellFormatType type, StringBuilder desc) { int pos = desc.Length; char firstCh = part[0]; switch (firstCh) { case 'e': case 'E': // See comment in WriteScientific -- exponent handling is complex. // (1) When parsing the format, remove the sign from After the 'e' and // Put it before the first digit of the exponent. if (formatter.exponent == null && formatter.specials.Count > 0) { formatter.specials.Add(formatter.exponent = new Special('.', pos)); insertSignForExponent = part[1]; return(part.Substring(0, 1)); } break; case '0': case '?': case '#': if (insertSignForExponent != '\0') { formatter.specials.Add(new Special(insertSignForExponent, pos)); desc.Append(insertSignForExponent); insertSignForExponent = '\0'; pos++; } for (int i = 0; i < part.Length; i++) { char ch = part[i]; formatter.specials.Add(new Special(ch, pos + i)); } break; case '.': if (formatter.decimalPoint == null && formatter.specials.Count > 0) { formatter.specials.Add(formatter.decimalPoint = new Special('.', pos)); } break; case '/': //!! This assumes there is a numerator and a denominator, but these are actually optional if (formatter.slash == null && formatter.specials.Count > 0) { formatter.numerator = formatter.previousNumber(); // If the first number in the whole format is the numerator, the // entire number should be printed as an improper fraction if (formatter.numerator == firstDigit(formatter.specials)) { formatter.improperFraction = true; } formatter.specials.Add(formatter.slash = new Special('.', pos)); } break; case '%': // don't need to remember because we don't need to do anything with these formatter.scale *= 100; break; default: return(null); } return(part); }
public string HandlePart(Match m, string part, CellFormatType type, StringBuilder desc) { int pos = desc.Length; char firstCh = part[0]; switch (firstCh) { case 's': case 'S': if (mStart >= 0) { for (int i = 0; i < mLen; i++) { desc[mStart + i] = 'm'; } mStart = -1; } return(part.ToLower()); case 'h': case 'H': mStart = -1; hStart = pos; hLen = part.Length; return(part.ToLower()); case 'd': case 'D': mStart = -1; //if (part.Length <= 2) return(part.ToLower()); //else // return part.ToLower().Replace('d', 'E'); case 'm': case 'M': mStart = pos; mLen = part.Length; // For 'm' after 'h', output minutes ('m') not month ('M') if (hStart >= 0) { return(part.ToLower()); } else { return(part.ToUpper()); } case 'y': case 'Y': mStart = -1; if (part.Length == 3) { part = "yyyy"; } return(part.ToLower()); case '0': mStart = -1; int sLen = part.Length; _formatter.sFmt = "%0" + (sLen + 2) + "." + sLen + "f"; _formatter.millisecondPartLength = sLen; return(part.Replace('0', 'f')); case 'a': case 'A': case 'p': case 'P': if (part.Length > 1) { // am/pm marker mStart = -1; _formatter.ShowAmPm = true; _formatter.ShowM = char.ToLower(part[1]) == 'm'; // For some reason "am/pm" becomes AM or PM, but "a/p" becomes a or p _formatter.amPmUpper = _formatter.ShowM || char.IsUpper(part[0]); if (_formatter.ShowM) { return("tt"); } else { return("t"); } //return "a"; } //noinspection fallthrough return(null); default: return(null); } }
public static StringBuilder ParseFormat(String fdesc, CellFormatType type, IPartHandler partHandler) { // Quoting is very awkward. In the Java classes, quoting is done // between ' chars, with '' meaning a single ' char. The problem is that // in Excel, it is legal to have two adjacent escaped strings. For // example, consider the Excel format "\a\b#". The naive (and easy) // translation into Java DecimalFormat is "'a''b'#". For the number 17, // in Excel you would Get "ab17", but in Java it would be "a'b17" -- the // '' is in the middle of the quoted string in Java. So the trick we // use is this: When we encounter a ' char in the Excel format, we // output a \u0000 char into the string. Now we know that any '' in the // output is the result of two adjacent escaped strings. So After the // main loop, we have to do two passes: One to eliminate any '' // sequences, to make "'a''b'" become "'ab'", and another to replace any // \u0000 with '' to mean a quote char. Oy. // // For formats that don't use "'" we don't do any of this MatchCollection mc = SPECIFICATION_PAT.Matches(fdesc); StringBuilder fmt = new StringBuilder(); Match lastMatch = null; //while (m.Find()) foreach (Match m in mc) { String part = Group(m, 0); if (part.Length > 0) { String repl = partHandler.HandlePart(m, part, type, fmt); if (repl == null) { switch (part[0]) { case '\"': repl = QuoteSpecial(part.Substring(1, part.Length - 2), type); break; case '\\': repl = QuoteSpecial(part.Substring(1), type); break; case '_': repl = " "; break; case '*': //!! We don't do this for real, we just Put in 3 of them repl = ExpandChar(part); break; default: repl = part; break; } } //m.AppendReplacement(fmt, Match.QuoteReplacement(repl)); fmt.Append(part.Replace(m.Captures[0].Value, repl)); if (m.NextMatch().Index - (m.Index + part.Length) > 0) { fmt.Append(fdesc.Substring(m.Index + part.Length, m.NextMatch().Index - (m.Index + part.Length))); } lastMatch = m; } } if (lastMatch != null) { fmt.Append(fdesc.Substring(lastMatch.Index + lastMatch.Groups[0].Value.Length)); } //m.AppendTail(fmt); if (type.IsSpecial('\'')) { // Now the next pass for quoted characters: Remove '' chars, making "'a''b'" into "'ab'" int pos = 0; while ((pos = fmt.ToString().IndexOf("''", pos)) >= 0) { //fmt.Delete(pos, pos + 2); fmt.Remove(pos, 2); } // Now the pass for quoted chars: Replace any \u0000 with '' pos = 0; while ((pos = fmt.ToString().IndexOf("\u0000", pos)) >= 0) { //fmt.Replace(pos, pos + 1, "''"); fmt.Remove(pos, 1); fmt.Insert(pos, "''"); } } return(fmt); }