- /* ====================================================================
- 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.
- ==================================================================== */
- package org.apache.poi.hssf.eventusermodel;
-
- import java.text.NumberFormat;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Locale;
- import java.util.Map;
-
- import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
- import org.apache.poi.hssf.record.CellValueRecordInterface;
- import org.apache.poi.hssf.record.ExtendedFormatRecord;
- import org.apache.poi.hssf.record.FormatRecord;
- import org.apache.poi.hssf.record.FormulaRecord;
- import org.apache.poi.hssf.record.NumberRecord;
- import org.apache.poi.hssf.record.Record;
- import org.apache.poi.hssf.usermodel.HSSFDataFormat;
- import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
- import org.apache.poi.util.LocaleUtil;
-
- import static org.apache.logging.log4j.util.Unbox.box;
-
- /**
- * A proxy HSSFListener that keeps track of the document formatting records, and
- * provides an easy way to look up the format strings used by cells from their
- * ids.
- */
- public class FormatTrackingHSSFListener implements HSSFListener {
- private static final Logger LOG = LogManager.getLogger(FormatTrackingHSSFListener.class);
- private final HSSFListener _childListener;
- private final HSSFDataFormatter _formatter;
- private final NumberFormat _defaultFormat;
- private final Map<Integer, FormatRecord> _customFormatRecords = new HashMap<>();
- private final List<ExtendedFormatRecord> _xfRecords = new ArrayList<>();
-
- /**
- * Creates a format tracking wrapper around the given listener, using
- * the {@link Locale#getDefault() default locale} for the formats.
- *
- * @param childListener the listener to be wrapped
- */
- public FormatTrackingHSSFListener(HSSFListener childListener) {
- this(childListener, LocaleUtil.getUserLocale());
- }
-
- /**
- * Creates a format tracking wrapper around the given listener, using
- * the given locale for the formats.
- *
- * @param childListener the listener to be wrapped
- * @param locale the locale for the formats
- */
- public FormatTrackingHSSFListener(
- HSSFListener childListener, Locale locale) {
- _childListener = childListener;
- _formatter = new HSSFDataFormatter(locale);
- _defaultFormat = NumberFormat.getInstance(locale);
- }
-
- protected int getNumberOfCustomFormats() {
- return _customFormatRecords.size();
- }
-
- protected int getNumberOfExtendedFormats() {
- return _xfRecords.size();
- }
-
- /**
- * Process this record ourselves, and then pass it on to our child listener
- */
- @Override
- public void processRecord(Record record) {
- // Handle it ourselves
- processRecordInternally(record);
-
- // Now pass on to our child
- _childListener.processRecord(record);
- }
-
- /**
- * Process the record ourselves, but do not pass it on to the child
- * Listener.
- *
- * @param record the record to be processed
- */
- public void processRecordInternally(Record record) {
- if (record instanceof FormatRecord) {
- FormatRecord fr = (FormatRecord) record;
- _customFormatRecords.put(Integer.valueOf(fr.getIndexCode()), fr);
- }
- if (record instanceof ExtendedFormatRecord) {
- ExtendedFormatRecord xr = (ExtendedFormatRecord) record;
- _xfRecords.add(xr);
- }
- }
-
- /**
- * Formats the given numeric of date cells contents as a String, in as
- * close as we can to the way that Excel would do so. Uses the various
- * format records to manage this.
- *
- * TODO - move this to a central class in such a way that hssf.usermodel can
- * make use of it too
- *
- * @param cell the cell
- *
- * @return the given numeric of date cells contents as a String
- */
- public String formatNumberDateCell(CellValueRecordInterface cell) {
- double value;
- if (cell instanceof NumberRecord) {
- value = ((NumberRecord) cell).getValue();
- } else if (cell instanceof FormulaRecord) {
- value = ((FormulaRecord) cell).getValue();
- } else {
- throw new IllegalArgumentException("Unsupported CellValue Record passed in " + cell);
- }
-
- // Get the built in format, if there is one
- int formatIndex = getFormatIndex(cell);
- String formatString = getFormatString(cell);
-
- if (formatString == null) {
- return _defaultFormat.format(value);
- }
- // Format, using the nice new
- // HSSFDataFormatter to do the work for us
- return _formatter.formatRawCellContents(value, formatIndex, formatString);
- }
-
- /**
- * Returns the format string, eg $##.##, for the given number format index.
- *
- * @param formatIndex the format index
- *
- * @return the format string
- */
- public String getFormatString(int formatIndex) {
- String format = null;
- if (formatIndex >= HSSFDataFormat.getNumberOfBuiltinBuiltinFormats()) {
- FormatRecord tfr = _customFormatRecords.get(Integer.valueOf(formatIndex));
- if (tfr == null) {
- LOG.atError().log("Requested format at index {}, but it wasn't found", box(formatIndex));
- } else {
- format = tfr.getFormatString();
- }
- } else {
- format = HSSFDataFormat.getBuiltinFormat((short) formatIndex);
- }
- return format;
- }
-
- /**
- * Returns the format string, eg $##.##, used by your cell
- *
- * @param cell the cell
- *
- * @return the format string
- */
- public String getFormatString(CellValueRecordInterface cell) {
- int formatIndex = getFormatIndex(cell);
- if (formatIndex == -1) {
- // Not found
- return null;
- }
- return getFormatString(formatIndex);
- }
-
- /**
- * Returns the index of the format string, used by your cell, or -1 if none found
- *
- * @param cell the cell
- *
- * @return the index of the format string
- */
- public int getFormatIndex(CellValueRecordInterface cell) {
- ExtendedFormatRecord xfr = _xfRecords.get(cell.getXFIndex());
- if (xfr == null) {
- LOG.atError().log("Cell {},{} uses XF with index {}, but we don't have that", box(cell.getRow()),box(cell.getColumn()),box(cell.getXFIndex()));
- return -1;
- }
- return xfr.getFormatIndex();
- }
- }
|