context: /* ====================================================================
     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 AL.Utils.NPOI.SS.Util
  {
      using System;
      using System.Text;
      using System.Text.RegularExpressions;
      using AL.Utils.NPOI.SS.Formula;
  using AL.Utils.NPOI.SS.UserModel;
      using System.Globalization;
  
      public enum NameType:int
      {
          /// <summary>
          /// Allow accessing the Initial value.
          /// </summary>
          None = 0,
          CELL = 1,
          NAMED_RANGE = 2,
          COLUMN = 3,
          ROW=4,
          BAD_CELL_OR_NAMED_RANGE = -1
      }
  
      /**
       *
       * @author  Avik Sengupta
       * @author  Dennis doubleday (patch to seperateRowColumns())
       */
      public class CellReference
      {
          /** The character ($) that signifies a row or column value is absolute instead of relative */
          private const char ABSOLUTE_REFERENCE_MARKER = '$';
          /** The character (!) that Separates sheet names from cell references */
          private const char SHEET_NAME_DELIMITER = '!';
          /** The character (') used to quote sheet names when they contain special characters */
          private const char SPECIAL_NAME_DELIMITER = '\'';
  
          /**
           * Matches a run of one or more letters followed by a run of one or more digits.
           * The run of letters is group 1 and the run of digits is group 2.  
           * Each group may optionally be prefixed with a single '$'.
           */
          private static string CELL_REF_PATTERN = @"^\$?([A-Za-z]+)\$?([0-9]+)";
          /**
           * Matches a run of one or more letters.  The run of letters is group 1.  
           * The text may optionally be prefixed with a single '$'.
           */
          private static string COLUMN_REF_PATTERN = @"^\$?([A-Za-z]+)$";
          /**
   * Matches a run of one or more digits.  The run of digits is group 1.
   * The text may optionally be prefixed with a single '$'.
   */
          private static string ROW_REF_PATTERN = @"^\$?([0-9]+)$";
          /**
           * Named range names must start with a letter or underscore.  Subsequent characters may include
           * digits or dot.  (They can even end in dot).
           */
          private static string NAMED_RANGE_NAME_PATTERN = "^[_A-Za-z][_.A-Za-z0-9]*$";
          //private static string BIFF8_LAST_COLUMN = "IV";
          //private static int BIFF8_LAST_COLUMN_TEXT_LEN = BIFF8_LAST_COLUMN.Length;
          //private static string BIFF8_LAST_ROW = (0x10000).ToString();
          //private static int BIFF8_LAST_ROW_TEXT_LEN = BIFF8_LAST_ROW.Length;
  
  
          private int _rowIndex;
          private int _colIndex;
          private String _sheetName;
          private bool _isRowAbs;
          private bool _isColAbs;
  
          /**
           * Create an cell ref from a string representation.  Sheet names containing special characters should be
           * delimited and escaped as per normal syntax rules for formulas.
           */
          public CellReference(String cellRef)
          {
              if (cellRef.EndsWith("#REF!", StringComparison.CurrentCulture))
              {
                  throw new ArgumentException("Cell reference invalid: " + cellRef);
              }
              String[] parts = SeparateRefParts(cellRef);
              _sheetName = parts[0];
              String colRef = parts[1];
              if (colRef.Length < 1)
              {
                  throw new ArgumentException("Invalid Formula cell reference: '" + cellRef + "'");
              }
              _isColAbs = colRef[0] == '$';
              if (_isColAbs)
              {
                  colRef = colRef.Substring(1);
              }
              _colIndex = ConvertColStringToIndex(colRef);
  
              String rowRef = parts[2];
              if (rowRef.Length < 1)
              {
                  throw new ArgumentException("Invalid Formula cell reference: '" + cellRef + "'");
              }
              _isRowAbs = rowRef[0] == '$';
              if (_isRowAbs)
              {
                  rowRef = rowRef.Substring(1);
              }
              _rowIndex = int.Parse(rowRef, CultureInfo.InvariantCulture) - 1; // -1 to convert 1-based to zero-based
          }
          public CellReference(ICell cell):this(cell.RowIndex, cell.ColumnIndex, false, false)
          {
              
          }
          public CellReference(int pRow, int pCol)
              : this(pRow, pCol, false, false)
          {
  
          }
          public CellReference(int pRow, short pCol)
              : this(pRow, pCol & 0xFFFF, false, false)
          {
  
          }
          public CellReference(int pRow, int pCol, bool pAbsRow, bool pAbsCol)
              : this(null, pRow, pCol, pAbsRow, pAbsCol)
          {
  
          }
          public CellReference(String pSheetName, int pRow, int pCol, bool pAbsRow, bool pAbsCol)
          {
              // TODO - "-1" is a special value being temporarily used for whole row and whole column area references.
              // so these Checks are currently N.Q.R.
              if (pRow < -1)
              {
                  throw new ArgumentException("row index may not be negative");
              }
              if (pCol < -1)
              {
                  throw new ArgumentException("column index may not be negative");
              }
              _sheetName = pSheetName;
              _rowIndex = pRow;
              _colIndex = pCol;
              _isRowAbs = pAbsRow;
              _isColAbs = pAbsCol;
          }
  
          public int Row
          {
              get { return _rowIndex; }
          }
          public short Col
          {
              get
              {
                  return (short)_colIndex;
              }
          }
          public bool IsRowAbsolute
          {
              get { return _isRowAbs; }
          }
          public bool IsColAbsolute
          {
              get { return _isColAbs; }
          }
          /**
            * @return possibly <c>null</c> if this is a 2D reference.  Special characters are not
            * escaped or delimited
            */
          public String SheetName
          {
              get { return _sheetName; }
          }
  
          /**
           * takes in a column reference portion of a CellRef and converts it from
           * ALPHA-26 number format to 0-based base 10.
           * 'A' -> 0
           * 'Z' -> 25
           * 'AA' -> 26
           * 'IV' -> 255
           * @return zero based column index
           */
          public static int ConvertColStringToIndex(String ref1)
          {
  
              int pos = 0;
              int retval = 0;
              for (int k = ref1.Length - 1; k >= 0; k--)
              {
                  char thechar = ref1[k];
                  if (thechar == ABSOLUTE_REFERENCE_MARKER)
                  {
                      if (k != 0)
                      {
                          throw new ArgumentException("Bad col ref format '"
                                  + ref1 + "'");
                      }
                      break;
                  }
                  // Character.getNumericValue() returns the values
                  //  10-35 for the letter A-Z
                  int shift = (int)Math.Pow(26, pos);
                  retval += (AL.Utils.NPOI.Util.Character.GetNumericValue(thechar) - 9) * shift;
                  pos++;
              }
              return retval - 1;
          }
          public static bool IsPartAbsolute(String part)
          {
              return part[0] == ABSOLUTE_REFERENCE_MARKER;
          }
          public static NameType ClassifyCellReference(String str, SpreadsheetVersion ssVersion)
          {
              int len = str.Length;
              if (len < 1)
              {
  
gt:                 throw new ArgumentException("Empty string not allowed");