All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.poi.hssf.record.DConRefRecord Maven / Gradle / Ivy

There is a newer version: 5.2.5
Show newest version
/*
 *  ====================================================================
 *    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.record;

import java.util.Arrays;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException;
import org.apache.poi.util.StringUtil;

/**
 * DConRef records specify a range in a workbook (internal or external) that serves as a data source
 * for pivot tables or data consolidation.
 *
 * Represents a {@code DConRef} Structure
 * [MS-XLS s.
 * 2.4.86], and the contained {@code DConFile} structure
 * 
 * [MS-XLS s. 2.5.69]. This in turn contains a {@code XLUnicodeStringNoCch}
 * 
 * [MS-XLS s. 2.5.296].
 *
 * 
 *         _______________________________
 *        |          DConRef              |
 *(bytes) +-+-+-+-+-+-+-+-+-+-+...+-+-+-+-+
 *        |    ref    |cch|  stFile   | un|
 *        +-+-+-+-+-+-+-+-+-+-+...+-+-+-+-+
 *                              |
 *                     _________|_____________________
 *                    |DConFile / XLUnicodeStringNoCch|
 *                    +-+-+-+-+-+-+-+-+-+-+-+...+-+-+-+
 *             (bits) |h|   reserved  |      rgb      |
 *                    +-+-+-+-+-+-+-+-+-+-+-+...+-+-+-+
 * 
* Where *
    *
  • {@code DConFile.h = 0x00} if the characters in{@code rgb} are single byte, and * {@code DConFile.h = 0x01} if they are double byte.

    * If they are double byte, then *

      *
    • If it exists, the length of {@code DConRef.un = 2}. Otherwise it is 1. *
    • The length of {@code DConFile.rgb = (2 * DConRef.cch)}. Otherwise it is equal to * {@code DConRef.cch}. *
    *
  • {@code DConRef.rgb} starts with {@code 0x01} if it is an external reference, * and with {@code 0x02} if it is a self-reference. *
* * At the moment this class is read-only. */ public class DConRefRecord extends StandardRecord { /** * The id of the record type, * sid = {@value} */ public static final short sid = 0x0051; /** * A RefU structure specifying the range of cells if this record is part of an SXTBL. * * [MS XLS s.2.5.211] */ private final int firstRow; private final int lastRow; private final int firstCol; private final int lastCol; /** * the number of chars in the link */ private final int charCount; /** * the type of characters (single or double byte) */ private final int charType; /** * The link's path string. This is the {@code rgb} field of a * {@code XLUnicodeStringNoCch}. Therefore it will contain at least one leading special * character (0x01 or 0x02) and probably other ones.

* @see * DConFile [MS-XLS s. 2.5.77] and * * VirtualPath [MS-XLS s. 2.5.69] */ private final byte[] path; /** * unused bits at the end, must be set to 0. */ private byte[] _unused; public DConRefRecord(DConRefRecord other) { super(other); firstCol = other.firstCol; firstRow = other.firstRow; lastCol = other.lastCol; lastRow = other.lastRow; charCount = other.charCount; charType = other.charType; path = (other.path == null) ? null : other.path.clone(); _unused = (other._unused == null) ? null : other._unused.clone(); } /** * Read constructor. * * @param data byte array containing a DConRef Record, including the header. */ public DConRefRecord(byte[] data) { this(bytesToRIStream(data)); } /** * Read Constructor. * * @param inStream RecordInputStream containing a DConRefRecord structure. */ public DConRefRecord(RecordInputStream inStream) { if (inStream.getSid() != sid) { throw new RecordFormatException("Wrong sid: " + inStream.getSid()); } firstRow = inStream.readUShort(); lastRow = inStream.readUShort(); firstCol = inStream.readUByte(); lastCol = inStream.readUByte(); charCount = inStream.readUShort(); // 7 bits reserved + 1 bit type - first bit only charType = inStream.readUByte() & 0x01; // bytelength is the length of the string in bytes, which depends on whether the string is // made of single- or double-byte chars. This is given by charType, which equals 0 if // single-byte, 1 if double-byte. final int byteLength = charCount * (charType + 1); path = IOUtils.safelyAllocate(byteLength, HSSFWorkbook.getMaxRecordLength()); inStream.readFully(path); // If it's a self reference, the last one or two bytes (depending on char type) are the // unused field. Not sure If i need to bother with this... if (path[0] == 0x02) { _unused = inStream.readRemainder(); } } /* * assuming this wants the number of bytes returned by {@link serialize(LittleEndianOutput)}, * that is, (length - 4). */ @Override protected int getDataSize() { int sz = 9 + path.length; if (path[0] == 0x02) sz += _unused.length; return sz; } @Override protected void serialize(LittleEndianOutput out) { out.writeShort(firstRow); out.writeShort(lastRow); out.writeByte(firstCol); out.writeByte(lastCol); out.writeShort(charCount); out.writeByte(charType); out.write(path); if (path[0] == 0x02) out.write(_unused); } @Override public short getSid() { return sid; } /** * @return The first column of the range. */ public int getFirstColumn() { return firstCol; } /** * @return The first row of the range. */ public int getFirstRow() { return firstRow; } /** * @return The last column of the range. */ public int getLastColumn() { return lastCol; } /** * @return The last row of the range. */ public int getLastRow() { return lastRow; } /** * * @return raw path byte array. */ public byte[] getPath() { return Arrays.copyOf(path, path.length); } /** * @return the link's path, with the special characters stripped/replaced. May be null. * See MS-XLS 2.5.277 (VirtualPath) */ public String getReadablePath() { if (path != null) { //all of the path strings start with either 0x02 or 0x01 followed by zero or //more of 0x01..0x08 int offset = 1; while (offset < path.length && path[offset] < 0x20) { offset++; } String out = new String(Arrays.copyOfRange(path, offset, path.length), StringUtil.UTF8); //UNC paths have \u0003 chars as path separators. out = out.replace("\u0003", "/"); return out; } return null; } /** * Checks if the data source in this reference record is external to this sheet or internal. * * @return true iff this is an external reference. */ public boolean isExternalRef() { return path[0] == 0x01; } @Override public DConRefRecord copy() { return new DConRefRecord(this); } private static RecordInputStream bytesToRIStream(byte[] data) { RecordInputStream ric = new RecordInputStream(new UnsynchronizedByteArrayInputStream(data)); ric.nextRecord(); return ric; } @Override public HSSFRecordTypes getGenericRecordType() { return HSSFRecordTypes.DCON_REF; } @Override public Map> getGenericProperties() { return GenericRecordUtil.getGenericProperties( "firstRow", this::getFirstRow, "lastRow", this::getLastRow, "firstColumn", this::getFirstColumn, "lastColumn", this::getLastColumn, "charCount", () -> charCount, "charType", () -> charType, "path", this::getReadablePath ); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy