first commit

This commit is contained in:
2025-07-28 13:56:49 +05:30
commit e9eb805edb
3438 changed files with 520990 additions and 0 deletions

View File

@@ -0,0 +1,680 @@
package jxl.write.biff;
import common.Assert;
import common.Logger;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import jxl.Range;
import jxl.Sheet;
import jxl.Workbook;
import jxl.WorkbookSettings;
import jxl.biff.ByteData;
import jxl.biff.CellReferenceHelper;
import jxl.biff.CountryCode;
import jxl.biff.Fonts;
import jxl.biff.FormattingRecords;
import jxl.biff.IndexMapping;
import jxl.biff.IntegerHelper;
import jxl.biff.RangeImpl;
import jxl.biff.WorkbookMethods;
import jxl.biff.drawing.Drawing;
import jxl.biff.drawing.DrawingGroup;
import jxl.biff.drawing.DrawingGroupObject;
import jxl.biff.drawing.Origin;
import jxl.biff.formula.ExternalSheet;
import jxl.format.Colour;
import jxl.format.RGB;
import jxl.read.biff.BOFRecord;
import jxl.read.biff.NameRecord;
import jxl.read.biff.SupbookRecord;
import jxl.read.biff.WorkbookParser;
import jxl.write.WritableCell;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
public class WritableWorkbookImpl extends WritableWorkbook implements ExternalSheet, WorkbookMethods {
private static Logger logger = Logger.getLogger(WritableWorkbookImpl.class);
private FormattingRecords formatRecords;
private File outputFile;
private ArrayList sheets;
private Fonts fonts;
private ExternalSheetRecord externSheet;
private ArrayList supbooks;
private ArrayList names;
private HashMap nameRecords;
private SharedStrings sharedStrings;
private boolean closeStream;
private boolean wbProtected;
private WorkbookSettings settings;
private ArrayList rcirCells;
private DrawingGroup drawingGroup;
private Styles styles;
private boolean containsMacros;
private ButtonPropertySetRecord buttonPropertySet;
private CountryRecord countryRecord;
public WritableWorkbookImpl(OutputStream os, boolean cs, WorkbookSettings ws) throws IOException {
this.outputFile = new File(os, ws, null);
this.sheets = new ArrayList();
this.sharedStrings = new SharedStrings();
this.nameRecords = new HashMap();
this.closeStream = cs;
this.wbProtected = false;
this.containsMacros = false;
this.settings = ws;
this.rcirCells = new ArrayList();
this.styles = new Styles();
WritableWorkbook.ARIAL_10_PT.uninitialize();
WritableWorkbook.HYPERLINK_FONT.uninitialize();
WritableWorkbook.NORMAL_STYLE.uninitialize();
WritableWorkbook.HYPERLINK_STYLE.uninitialize();
WritableWorkbook.HIDDEN_STYLE.uninitialize();
DateRecord.defaultDateFormat.uninitialize();
WritableFonts wf = new WritableFonts(this);
this.fonts = wf;
WritableFormattingRecords wfr = new WritableFormattingRecords(this.fonts, this.styles);
this.formatRecords = wfr;
}
public WritableWorkbookImpl(OutputStream os, Workbook w, boolean cs, WorkbookSettings ws) throws IOException {
WorkbookParser wp = (WorkbookParser)w;
WritableWorkbook.ARIAL_10_PT.uninitialize();
WritableWorkbook.HYPERLINK_FONT.uninitialize();
WritableWorkbook.NORMAL_STYLE.uninitialize();
WritableWorkbook.HYPERLINK_STYLE.uninitialize();
WritableWorkbook.HIDDEN_STYLE.uninitialize();
DateRecord.defaultDateFormat.uninitialize();
this.closeStream = cs;
this.sheets = new ArrayList();
this.sharedStrings = new SharedStrings();
this.nameRecords = new HashMap();
this.fonts = wp.getFonts();
this.formatRecords = wp.getFormattingRecords();
this.wbProtected = false;
this.settings = ws;
this.rcirCells = new ArrayList();
this.styles = new Styles();
this.outputFile = new File(os, ws, wp.getCompoundFile());
this.containsMacros = false;
if (!ws.getPropertySetsDisabled())
this.containsMacros = wp.containsMacros();
if (wp.getCountryRecord() != null)
this.countryRecord = new CountryRecord(wp.getCountryRecord());
if (wp.getExternalSheetRecord() != null) {
this.externSheet = new ExternalSheetRecord(wp.getExternalSheetRecord());
SupbookRecord[] readsr = wp.getSupbookRecords();
this.supbooks = new ArrayList(readsr.length);
for (int i = 0; i < readsr.length; i++)
this.supbooks.add(new SupbookRecord(readsr[i], this.settings));
}
if (wp.getDrawingGroup() != null)
this.drawingGroup = new DrawingGroup(wp.getDrawingGroup());
if (this.containsMacros && wp.getButtonPropertySet() != null)
this.buttonPropertySet = new ButtonPropertySetRecord(wp.getButtonPropertySet());
if (!this.settings.getNamesDisabled()) {
NameRecord[] na = wp.getNameRecords();
this.names = new ArrayList(na.length);
for (int i = 0; i < na.length; i++) {
if (na[i].isBiff8()) {
NameRecord n = new NameRecord(na[i], i);
this.names.add(n);
String name = n.getName();
this.nameRecords.put(name, n);
} else {
logger.warn("Cannot copy Biff7 name records - ignoring");
}
}
}
copyWorkbook(w);
if (this.drawingGroup != null)
this.drawingGroup.updateData(wp.getDrawingGroup());
}
public WritableSheet[] getSheets() {
WritableSheet[] sheetArray = new WritableSheet[getNumberOfSheets()];
for (int i = 0; i < getNumberOfSheets(); i++)
sheetArray[i] = getSheet(i);
return sheetArray;
}
public String[] getSheetNames() {
String[] sheetNames = new String[getNumberOfSheets()];
for (int i = 0; i < sheetNames.length; i++)
sheetNames[i] = getSheet(i).getName();
return sheetNames;
}
public Sheet getReadSheet(int index) {
return (Sheet)getSheet(index);
}
public WritableSheet getSheet(int index) {
return this.sheets.get(index);
}
public WritableSheet getSheet(String name) {
boolean found = false;
Iterator i = this.sheets.iterator();
WritableSheet s = null;
while (i.hasNext() && !found) {
s = i.next();
if (s.getName().equals(name))
found = true;
}
return found ? s : null;
}
public int getNumberOfSheets() {
return this.sheets.size();
}
public void close() throws IOException, JxlWriteException {
this.outputFile.close(this.closeStream);
}
public void setOutputFile(File fileName) throws IOException {
FileOutputStream fos = new FileOutputStream(fileName);
this.outputFile.setOutputFile(fos);
}
private WritableSheet createSheet(String name, int index, boolean handleRefs) {
WritableSheet w = new WritableSheetImpl(name, this.outputFile, this.formatRecords, this.sharedStrings, this.settings, this);
int pos = index;
if (index <= 0) {
pos = 0;
this.sheets.add(0, w);
} else if (index > this.sheets.size()) {
pos = this.sheets.size();
this.sheets.add(w);
} else {
this.sheets.add(index, w);
}
if (handleRefs && this.externSheet != null)
this.externSheet.sheetInserted(pos);
if (this.supbooks != null && this.supbooks.size() > 0) {
SupbookRecord supbook = this.supbooks.get(0);
if (supbook.getType() == SupbookRecord.INTERNAL)
supbook.adjustInternal(this.sheets.size());
}
return w;
}
public WritableSheet createSheet(String name, int index) {
return createSheet(name, index, true);
}
public void removeSheet(int index) {
int pos = index;
if (index <= 0) {
pos = 0;
this.sheets.remove(0);
} else if (index >= this.sheets.size()) {
pos = this.sheets.size() - 1;
this.sheets.remove(this.sheets.size() - 1);
} else {
this.sheets.remove(index);
}
if (this.externSheet != null)
this.externSheet.sheetRemoved(pos);
if (this.supbooks != null && this.supbooks.size() > 0) {
SupbookRecord supbook = this.supbooks.get(0);
if (supbook.getType() == SupbookRecord.INTERNAL)
supbook.adjustInternal(this.sheets.size());
}
if (this.names != null && this.names.size() > 0)
for (int i = 0; i < this.names.size(); i++) {
NameRecord n = this.names.get(i);
int oldRef = n.getSheetRef();
if (oldRef == pos + 1) {
n.setSheetRef(0);
} else if (oldRef > pos + 1) {
if (oldRef < 1)
oldRef = 1;
n.setSheetRef(oldRef - 1);
}
}
}
public WritableSheet moveSheet(int fromIndex, int toIndex) {
fromIndex = Math.max(fromIndex, 0);
fromIndex = Math.min(fromIndex, this.sheets.size() - 1);
toIndex = Math.max(toIndex, 0);
toIndex = Math.min(toIndex, this.sheets.size() - 1);
WritableSheet sheet = this.sheets.remove(fromIndex);
this.sheets.add(toIndex, sheet);
return sheet;
}
public void write() throws IOException {
WritableSheetImpl wsi = null;
for (int i = 0; i < getNumberOfSheets(); i++) {
wsi = (WritableSheetImpl)getSheet(i);
wsi.checkMergedBorders();
}
if (!this.settings.getRationalizationDisabled())
rationalize();
BOFRecord bof = new BOFRecord(BOFRecord.workbookGlobals);
this.outputFile.write((ByteData)bof);
InterfaceHeaderRecord ihr = new InterfaceHeaderRecord();
this.outputFile.write((ByteData)ihr);
MMSRecord mms = new MMSRecord(0, 0);
this.outputFile.write((ByteData)mms);
InterfaceEndRecord ier = new InterfaceEndRecord();
this.outputFile.write((ByteData)ier);
WriteAccessRecord wr = new WriteAccessRecord();
this.outputFile.write((ByteData)wr);
CodepageRecord cp = new CodepageRecord();
this.outputFile.write((ByteData)cp);
DSFRecord dsf = new DSFRecord();
this.outputFile.write((ByteData)dsf);
TabIdRecord tabid = new TabIdRecord(getNumberOfSheets());
this.outputFile.write((ByteData)tabid);
if (this.containsMacros) {
ObjProjRecord objproj = new ObjProjRecord();
this.outputFile.write((ByteData)objproj);
}
if (this.buttonPropertySet != null)
this.outputFile.write((ByteData)this.buttonPropertySet);
FunctionGroupCountRecord fgcr = new FunctionGroupCountRecord();
this.outputFile.write((ByteData)fgcr);
WindowProtectRecord wpr = new WindowProtectRecord(false);
this.outputFile.write((ByteData)wpr);
ProtectRecord pr = new ProtectRecord(this.wbProtected);
this.outputFile.write((ByteData)pr);
PasswordRecord pw = new PasswordRecord(null);
this.outputFile.write((ByteData)pw);
Prot4RevRecord p4r = new Prot4RevRecord(false);
this.outputFile.write((ByteData)p4r);
Prot4RevPassRecord p4rp = new Prot4RevPassRecord();
this.outputFile.write((ByteData)p4rp);
Window1Record w1r = new Window1Record();
this.outputFile.write((ByteData)w1r);
BackupRecord bkr = new BackupRecord(false);
this.outputFile.write((ByteData)bkr);
HideobjRecord ho = new HideobjRecord(false);
this.outputFile.write((ByteData)ho);
NineteenFourRecord nf = new NineteenFourRecord(false);
this.outputFile.write((ByteData)nf);
PrecisionRecord pc = new PrecisionRecord(false);
this.outputFile.write((ByteData)pc);
RefreshAllRecord rar = new RefreshAllRecord(false);
this.outputFile.write((ByteData)rar);
BookboolRecord bb = new BookboolRecord(true);
this.outputFile.write((ByteData)bb);
this.fonts.write(this.outputFile);
this.formatRecords.write(this.outputFile);
if (this.formatRecords.getPalette() != null)
this.outputFile.write((ByteData)this.formatRecords.getPalette());
UsesElfsRecord uer = new UsesElfsRecord();
this.outputFile.write((ByteData)uer);
int[] boundsheetPos = new int[getNumberOfSheets()];
Sheet sheet = null;
int j;
for (j = 0; j < getNumberOfSheets(); j++) {
boundsheetPos[j] = this.outputFile.getPos();
WritableSheet writableSheet = getSheet(j);
BoundsheetRecord br = new BoundsheetRecord(writableSheet.getName());
if (writableSheet.getSettings().isHidden())
br.setHidden();
if (((WritableSheetImpl)this.sheets.get(j)).isChartOnly())
br.setChartOnly();
this.outputFile.write((ByteData)br);
}
if (this.countryRecord == null) {
CountryCode lang = CountryCode.getCountryCode(this.settings.getExcelDisplayLanguage());
if (lang == CountryCode.UNKNOWN) {
logger.warn("Unknown country code " + this.settings.getExcelDisplayLanguage() + " using " + CountryCode.USA.getCode());
lang = CountryCode.USA;
}
CountryCode region = CountryCode.getCountryCode(this.settings.getExcelRegionalSettings());
this.countryRecord = new CountryRecord(lang, region);
if (region == CountryCode.UNKNOWN) {
logger.warn("Unknown country code " + this.settings.getExcelDisplayLanguage() + " using " + CountryCode.UK.getCode());
region = CountryCode.UK;
}
}
this.outputFile.write((ByteData)this.countryRecord);
if (this.externSheet != null) {
for (j = 0; j < this.supbooks.size(); j++) {
SupbookRecord supbook = this.supbooks.get(j);
this.outputFile.write((ByteData)supbook);
}
this.outputFile.write((ByteData)this.externSheet);
}
if (this.names != null)
for (j = 0; j < this.names.size(); j++) {
NameRecord n = this.names.get(j);
this.outputFile.write((ByteData)n);
}
if (this.drawingGroup != null)
this.drawingGroup.write(this.outputFile);
this.sharedStrings.write(this.outputFile);
EOFRecord eof = new EOFRecord();
this.outputFile.write((ByteData)eof);
boolean sheetSelected = false;
WritableSheetImpl wsheet = null;
int k;
for (k = 0; k < getNumberOfSheets() && !sheetSelected; k++) {
wsheet = (WritableSheetImpl)getSheet(k);
if (wsheet.getSettings().isSelected())
sheetSelected = true;
}
if (!sheetSelected) {
wsheet = (WritableSheetImpl)getSheet(0);
wsheet.getSettings().setSelected(true);
}
for (k = 0; k < getNumberOfSheets(); k++) {
this.outputFile.setData(IntegerHelper.getFourBytes(this.outputFile.getPos()), boundsheetPos[k] + 4);
wsheet = (WritableSheetImpl)getSheet(k);
wsheet.write();
}
}
private void copyWorkbook(Workbook w) {
int numSheets = w.getNumberOfSheets();
this.wbProtected = w.isProtected();
Sheet s = null;
WritableSheetImpl ws = null;
for (int i = 0; i < numSheets; i++) {
s = w.getSheet(i);
ws = (WritableSheetImpl)createSheet(s.getName(), i, false);
ws.copy(s);
}
}
public void copySheet(int s, String name, int index) {
WritableSheet sheet = getSheet(s);
WritableSheetImpl ws = (WritableSheetImpl)createSheet(name, index);
ws.copy(sheet);
}
public void copySheet(String s, String name, int index) {
WritableSheet sheet = getSheet(s);
WritableSheetImpl ws = (WritableSheetImpl)createSheet(name, index);
ws.copy(sheet);
}
public void setProtected(boolean prot) {
this.wbProtected = prot;
}
private void rationalize() {
IndexMapping fontMapping = this.formatRecords.rationalizeFonts();
IndexMapping formatMapping = this.formatRecords.rationalizeDisplayFormats();
IndexMapping xfMapping = this.formatRecords.rationalize(fontMapping, formatMapping);
WritableSheetImpl wsi = null;
for (int i = 0; i < this.sheets.size(); i++) {
wsi = this.sheets.get(i);
wsi.rationalize(xfMapping, fontMapping, formatMapping);
}
}
public String getExternalSheetName(int index) {
int supbookIndex = this.externSheet.getSupbookIndex(index);
SupbookRecord sr = this.supbooks.get(supbookIndex);
int firstTab = this.externSheet.getFirstTabIndex(index);
if (sr.getType() == SupbookRecord.INTERNAL) {
WritableSheet ws = getSheet(firstTab);
return ws.getName();
}
if (sr.getType() == SupbookRecord.EXTERNAL) {
String name = sr.getFileName() + sr.getSheetName(firstTab);
return name;
}
return "[UNKNOWN]";
}
public String getLastExternalSheetName(int index) {
int supbookIndex = this.externSheet.getSupbookIndex(index);
SupbookRecord sr = this.supbooks.get(supbookIndex);
int lastTab = this.externSheet.getLastTabIndex(index);
if (sr.getType() == SupbookRecord.INTERNAL) {
WritableSheet ws = getSheet(lastTab);
return ws.getName();
}
if (sr.getType() == SupbookRecord.EXTERNAL)
Assert.verify(false);
return "[UNKNOWN]";
}
public BOFRecord getWorkbookBof() {
return null;
}
public int getExternalSheetIndex(int index) {
if (this.externSheet == null)
return index;
Assert.verify((this.externSheet != null));
int firstTab = this.externSheet.getFirstTabIndex(index);
return firstTab;
}
public int getLastExternalSheetIndex(int index) {
if (this.externSheet == null)
return index;
Assert.verify((this.externSheet != null));
int lastTab = this.externSheet.getLastTabIndex(index);
return lastTab;
}
public int getExternalSheetIndex(String sheetName) {
if (this.externSheet == null) {
this.externSheet = new ExternalSheetRecord();
this.supbooks = new ArrayList();
this.supbooks.add(new SupbookRecord(getNumberOfSheets(), this.settings));
}
boolean found = false;
Iterator i = this.sheets.iterator();
int sheetpos = 0;
WritableSheetImpl s = null;
while (i.hasNext() && !found) {
s = i.next();
if (s.getName().equals(sheetName)) {
found = true;
continue;
}
sheetpos++;
}
if (found) {
SupbookRecord supbook = this.supbooks.get(0);
Assert.verify((supbook.getType() == SupbookRecord.INTERNAL && supbook.getNumberOfSheets() == getNumberOfSheets()));
return this.externSheet.getIndex(0, sheetpos);
}
int closeSquareBracketsIndex = sheetName.lastIndexOf(']');
int openSquareBracketsIndex = sheetName.lastIndexOf('[');
if (closeSquareBracketsIndex == -1 || openSquareBracketsIndex == -1)
return -1;
String worksheetName = sheetName.substring(closeSquareBracketsIndex + 1);
String workbookName = sheetName.substring(openSquareBracketsIndex + 1, closeSquareBracketsIndex);
String path = sheetName.substring(0, openSquareBracketsIndex);
String fileName = path + workbookName;
boolean supbookFound = false;
SupbookRecord externalSupbook = null;
int supbookIndex = -1;
for (int ind = 0; ind < this.supbooks.size() && !supbookFound; ind++) {
externalSupbook = this.supbooks.get(ind);
if (externalSupbook.getType() == SupbookRecord.EXTERNAL && externalSupbook.getFileName().equals(fileName)) {
supbookFound = true;
supbookIndex = ind;
}
}
if (!supbookFound) {
externalSupbook = new SupbookRecord(fileName, this.settings);
supbookIndex = this.supbooks.size();
this.supbooks.add(externalSupbook);
}
int sheetIndex = externalSupbook.getSheetIndex(worksheetName);
return this.externSheet.getIndex(supbookIndex, sheetIndex);
}
public int getLastExternalSheetIndex(String sheetName) {
if (this.externSheet == null) {
this.externSheet = new ExternalSheetRecord();
this.supbooks = new ArrayList();
this.supbooks.add(new SupbookRecord(getNumberOfSheets(), this.settings));
}
boolean found = false;
Iterator i = this.sheets.iterator();
int sheetpos = 0;
WritableSheetImpl s = null;
while (i.hasNext() && !found) {
s = i.next();
if (s.getName().equals(sheetName)) {
found = true;
continue;
}
sheetpos++;
}
if (!found)
return -1;
SupbookRecord supbook = this.supbooks.get(0);
Assert.verify((supbook.getType() == SupbookRecord.INTERNAL && supbook.getNumberOfSheets() == getNumberOfSheets()));
return this.externSheet.getIndex(0, sheetpos);
}
public void setColourRGB(Colour c, int r, int g, int b) {
this.formatRecords.setColourRGB(c, r, g, b);
}
public RGB getColourRGB(Colour c) {
return this.formatRecords.getColourRGB(c);
}
public String getName(int index) {
Assert.verify((index >= 0 && index < this.names.size()));
NameRecord n = this.names.get(index);
return n.getName();
}
public int getNameIndex(String name) {
NameRecord nr = (NameRecord)this.nameRecords.get(name);
return (nr != null) ? nr.getIndex() : -1;
}
void addRCIRCell(CellValue cv) {
this.rcirCells.add(cv);
}
void columnInserted(WritableSheetImpl s, int col) {
int externalSheetIndex = getExternalSheetIndex(s.getName());
for (Iterator i = this.rcirCells.iterator(); i.hasNext(); ) {
CellValue cv = i.next();
cv.columnInserted((Sheet)s, externalSheetIndex, col);
}
}
void columnRemoved(WritableSheetImpl s, int col) {
int externalSheetIndex = getExternalSheetIndex(s.getName());
for (Iterator i = this.rcirCells.iterator(); i.hasNext(); ) {
CellValue cv = i.next();
cv.columnRemoved((Sheet)s, externalSheetIndex, col);
}
}
void rowInserted(WritableSheetImpl s, int row) {
int externalSheetIndex = getExternalSheetIndex(s.getName());
for (Iterator i = this.rcirCells.iterator(); i.hasNext(); ) {
CellValue cv = i.next();
cv.rowInserted((Sheet)s, externalSheetIndex, row);
}
}
void rowRemoved(WritableSheetImpl s, int row) {
int externalSheetIndex = getExternalSheetIndex(s.getName());
for (Iterator i = this.rcirCells.iterator(); i.hasNext(); ) {
CellValue cv = i.next();
cv.rowRemoved((Sheet)s, externalSheetIndex, row);
}
}
public WritableCell findCellByName(String name) {
NameRecord nr = (NameRecord)this.nameRecords.get(name);
if (nr == null)
return null;
NameRecord.NameRange[] ranges = nr.getRanges();
int sheetIndex = getExternalSheetIndex(ranges[0].getExternalSheet());
WritableSheet s = getSheet(sheetIndex);
WritableCell cell = s.getWritableCell(ranges[0].getFirstColumn(), ranges[0].getFirstRow());
return cell;
}
public Range[] findByName(String name) {
NameRecord nr = (NameRecord)this.nameRecords.get(name);
if (nr == null)
return null;
NameRecord.NameRange[] ranges = nr.getRanges();
Range[] cellRanges = new Range[ranges.length];
for (int i = 0; i < ranges.length; i++)
cellRanges[i] = (Range)new RangeImpl(this, getExternalSheetIndex(ranges[i].getExternalSheet()), ranges[i].getFirstColumn(), ranges[i].getFirstRow(), getLastExternalSheetIndex(ranges[i].getExternalSheet()), ranges[i].getLastColumn(), ranges[i].getLastRow());
return cellRanges;
}
void addDrawing(DrawingGroupObject d) {
if (this.drawingGroup == null)
this.drawingGroup = new DrawingGroup(Origin.WRITE);
this.drawingGroup.add(d);
}
void removeDrawing(Drawing d) {
Assert.verify((this.drawingGroup != null));
this.drawingGroup.remove((DrawingGroupObject)d);
}
DrawingGroup getDrawingGroup() {
return this.drawingGroup;
}
public String[] getRangeNames() {
String[] n = new String[this.names.size()];
for (int i = 0; i < this.names.size(); i++) {
NameRecord nr = this.names.get(i);
n[i] = nr.getName();
}
return n;
}
Styles getStyles() {
return this.styles;
}
public void addNameArea(String name, WritableSheet sheet, int firstCol, int firstRow, int lastCol, int lastRow) {
if (this.names == null)
this.names = new ArrayList();
int externalSheetIndex = getExternalSheetIndex(sheet.getName());
NameRecord nr = new NameRecord(name, this.names.size(), externalSheetIndex, firstRow, lastRow, firstCol, lastCol);
this.names.add(nr);
this.nameRecords.put(name, nr);
}
WorkbookSettings getSettings() {
return this.settings;
}
public WritableCell getWritableCell(String loc) {
WritableSheet s = getSheet(CellReferenceHelper.getSheet(loc));
return s.getWritableCell(loc);
}
}