/**
   * Creates the {@link AbstractAddress} from a {@link Spreadsheet} specified by a String in A1
   * Notion.
   *
   * @param a1Notion
   * @return
   */
  private static AbstractAddress createCellAddress(String a1Notion) {
    CellAddress address = null;

    if (Character.isLetter(a1Notion.charAt(0))
        && Character.isDigit(a1Notion.charAt(a1Notion.length() - 1))) {
      Integer horizontalIndex = 0;
      Integer verticalIndex = 0;

      // First convert the letters to the column index
      int i = 0;
      char currentChar = a1Notion.charAt(i);

      while (i < a1Notion.length() && Character.isLetter(currentChar)) {
        horizontalIndex += characterToColumnIndex(currentChar);
        i++;
        currentChar = a1Notion.charAt(i);
      }

      // Then convert the number part to the row index
      if (Character.isDigit(currentChar)) {
        verticalIndex = Integer.parseInt(a1Notion.substring(i));
      }

      address = new CellAddress();
      address.setColumnIndex(horizontalIndex);
      address.setRowIndex(verticalIndex);
    }

    return address;
  }
  /**
   * * Transforms a given OperandPtg to its correspondent in the internal model.
   *
   * @param ptg The given OperandPtg
   * @return The correspondent of the given OperandPtg in the internal model.
   */
  private AbstractReference transform(Cell cell, OperandPtg ptg) {
    AbstractReference reference = null;
    // Cell-Reference.
    if (ptg instanceof RefPtgBase) {
      RefPtgBase refPtgBase = (RefPtgBase) ptg;

      // Create new cell reference.
      CellReference cellReference = new CellReference();
      reference = cellReference;

      // Create referenced address.
      CellAddress referencedCellAddress = new CellAddress();
      referencedCellAddress.setColumnIndex(refPtgBase.getColumn() + 1);
      referencedCellAddress.setRowIndex(refPtgBase.getRow() + 1);
      referencedCellAddress.setWorksheet(cell.getWorksheet());

      // Cell reference is within worksheet.
      if (ptg instanceof RefPtg) {
        referencedCellAddress.setWorksheet(cell.getWorksheet());
      }
      // Cell reference is to a different worksheet.
      if (refPtgBase instanceof Ref3DPtg) {
        Ref3DPtg ref3DPtg = (Ref3DPtg) refPtgBase;
        Workbook poiWorkbook = poiIO.poiWorkbook;
        Integer sheetIndex = null;

        // Get the sheet index.
        if (poiWorkbook instanceof HSSFWorkbook) {
          sheetIndex =
              ((HSSFWorkbook) poiWorkbook)
                  .getSheetIndexFromExternSheetIndex(ref3DPtg.getExternSheetIndex());
        } else {
          sheetIndex = ref3DPtg.getExternSheetIndex();
        }

        // Transform sheet index to a 1 based index.
        referencedCellAddress.setWorksheet(poiIO.spreadsheet.getWorksheetAt(sheetIndex + 1));
      }

      // Get referenced cell.
      Cell referencedCell = poiIO.spreadsheet.getCellFor(referencedCellAddress);

      // Create blank cell if referenced cell does not exist.
      if (referencedCell == null) {
        referencedCell = new Cell();
        referencedCell.setColumnIndex(referencedCellAddress.getColumnIndex());
        referencedCell.setRowIndex(referencedCellAddress.getRowIndex());
        Worksheet worksheet = referencedCellAddress.getWorksheet();
        referencedCell.setWorksheet(worksheet);
        worksheet.add(referencedCell);
      }

      // Set up cell reference.
      cellReference.setColumnRelative(refPtgBase.isColRelative());
      cellReference.setRowRelative(refPtgBase.isRowRelative());
      cellReference.setReferencedElement(referencedCell);
      cellReference.setReferencingElement(cell);
    }

    // Range-Reference.
    if (ptg instanceof AreaPtgBase) {
      AreaPtgBase areaPtgBase = (AreaPtgBase) ptg;

      // Create new range reference.
      RangeReference rangeReference = new RangeReference();
      reference = rangeReference;

      // Create address.
      RangeAddress referencedRangeAddress = new RangeAddress();
      referencedRangeAddress.setLeftmostColumnIndex(areaPtgBase.getFirstColumn() + 1);
      referencedRangeAddress.setTopmostRowIndex(areaPtgBase.getFirstRow() + 1);
      referencedRangeAddress.setRightmostColumnIndex(areaPtgBase.getLastColumn() + 1);
      referencedRangeAddress.setBottommostRowIndex(areaPtgBase.getLastRow() + 1);
      referencedRangeAddress.setWorksheet(cell.getWorksheet());
      // Reference is within worksheet.
      if (areaPtgBase instanceof AreaPtg) {
        referencedRangeAddress.setWorksheet(cell.getWorksheet());
      }
      // Reference is to a different worksheet.
      if (areaPtgBase instanceof Area3DPtg) {
        Area3DPtg area3DPtg = (Area3DPtg) areaPtgBase;
        referencedRangeAddress.setWorksheet(
            poiIO.spreadsheet.getWorksheetAt(area3DPtg.getExternSheetIndex() + 1));
      }

      // Create blank cells if needed.
      poiIO.spreadsheet.createBlankCellsForNullCellsIn(referencedRangeAddress);

      // Get referenced range.
      Range referencedRange = poiIO.spreadsheet.getRangeFor(referencedRangeAddress);

      // Set up range reference.
      rangeReference.setReferencedElement(referencedRange);
      rangeReference.setReferencingElement(cell);

      rangeReference.setLeftmostColumnRelative(areaPtgBase.isFirstColRelative());
      rangeReference.setTopmostRowRelative(areaPtgBase.isFirstRowRelative());
      rangeReference.setRightmostColumnRelative(areaPtgBase.isLastColRelative());
      rangeReference.setBottommostRowRelative(areaPtgBase.isLastRowRelative());
    }

    return reference;
  }