org.ttzero.excel.entity.Workbook Maven / Gradle / Ivy
/*
* Copyright (c) 2019, [email protected] All Rights Reserved.
*
* Licensed 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.ttzero.excel.entity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.ttzero.excel.entity.e7.XMLWorkbookWriter;
import org.ttzero.excel.entity.style.Fill;
import org.ttzero.excel.entity.style.Styles;
import org.ttzero.excel.processor.ParamProcessor;
import org.ttzero.excel.processor.Watch;
import org.ttzero.excel.util.FileUtil;
import javax.naming.OperationNotSupportedException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* The workbook is the basic unit of Excel, and an 'xlsx' or 'xls' file
* corresponds to a workbook instance.
*
* When writing an Excel file, you must setting the property first and
* then add {@link Sheet} into Workbook, finally call the {@link #writeTo}
* method to perform the write operation. The default file format is open-xml(xlsx).
* You can also call the {@link #saveAsExcel2003()} method to output as 'xls'
* format (only supported BIFF8 format, ie excel 97~2003).
*
* The property contains {@link #setName(String)}, {@link #setCreator(String)},
* {@link #setCompany(String)}, {@link #setAutoSize(boolean)} and {@link #setOddFill(Fill)}
* You can also call {@link #setWorkbookWriter(IWorkbookWriter)} method to setting
* a custom WorkbookWriter to achieve special demand.
*
* The {@link #writeTo} method is a terminating statement, and all settings
* placed after this statement will not be reflected in the final Excel file.
*
* A typical example as follow:
*
* new Workbook("{name}", "{author}")
* // Print debug logs
* .watch(System.out::println)
* // Auto size the column width
* .setAutoSize(true)
* // Add a Worksheet
* .addSheet(new ListSheet<ListObjectSheetTest.Item>("{worksheet name}").setData(new ArrayList<>()))
* // Add an other Worksheet
* .addSheet(new ListMapSheet("{worksheet name}").setData(new ArrayList<>()))
* // Write to absolute path '/tmp/{name}.xlsx'
* .writeTo(Paths.get("/tmp/"));
* Some referer links:
* POI |
* Office 365 |
* DocumentFormat.OpenXml.Spreadsheet Namespace |
* 介绍 Microsoft Office (2007) Open XML 文件格式
*
* Created by guanquan.wang on 2017/9/26.
*/
public class Workbook implements Storageable {
private Logger logger = LogManager.getLogger(getClass());
/**
* The Workbook name, reaction to the Excel file name
*/
private String name;
private Sheet[] sheets;
private WaterMark waterMark;
private int size;
private Connection con;
/**
* Auto size flag
*/
private boolean autoSize;
/**
* Automatic interlacing fill, default fill color is '#E2EDDA'
*/
private int autoOdd = 0;
private String creator, company;
/**
* The fill
*/
private Fill oddFill;
/**
* A windows to debug
*/
private Watch watch;
private I18N i18N;
private SharedStrings sst;
private Styles styles;
private IWorkbookWriter workbookWriter;
/**
* Create a unnamed workbook
*
* EEC finds the 'non-name-file' keyword under the {@code resources/I18N/message.XXX.properties}
* file first. If there contains the keyword, use this value as the default file name,
* otherwise use 'Non name' as the name.
*/
public Workbook() {
this(null);
}
/**
* Create a workbook with the specified name. Use this name as
* the file name when saving to disk
*
* @param name the workbook name
*/
public Workbook(String name) {
this(name, null);
}
/**
* Create a workbook with the specified name and author.
*
* @param name the workbook name
* @param creator the author, it will getting the
* {@code System.getProperty("user.name")} if it not be setting.
*/
public Workbook(String name, String creator) {
this.name = name;
this.creator = creator;
sheets = new Sheet[3]; // 默认建3个sheet页
sst = new SharedStrings();
i18N = new I18N();
// Create a global styles
styles = Styles.create(i18N);
// Default writer
workbookWriter = new XMLWorkbookWriter(this);
}
/**
* Returns the workbook name
*
* @return the workbook name
*/
public String getName() {
return name;
}
/**
* Setting the workbook name
*
* @param name the workbook name
* @return the {@link Workbook}
*/
public Workbook setName(String name) {
this.name = name;
return this;
}
/**
* Returns the autoOdd setting
*
* @return 1 if odd-fill
*/
public int getAutoOdd() {
return autoOdd;
}
/**
* Returns the excel author
*
* @return the author
*/
public String getCreator() {
return creator;
}
/**
* Returns the company name where the author is employed
*
* @return the company name
*/
public String getCompany() {
return company;
}
/**
* Returns the odd-fill style
*
* @return the {@link Fill} style
*/
public Fill getOddFill() {
return oddFill;
}
/**
* Returns the {@link I18N} util
*
* @return the {@link I18N} util
*/
public I18N getI18N() {
return i18N;
}
/**
* Returns the size of {@link Sheet} in this workbook
*
* @return ths size of Worksheet
*/
public int getSize() {
return size;
}
/**
* Returns the Shared String Table
*
* @return the global {@link SharedStrings}
*/
public SharedStrings getSst() {
return sst;
}
/**
* Returns all {@link Sheet} in this workbook
*
* @return array of {@link Sheet}
*/
public final Sheet[] getSheets() {
return Arrays.copyOf(sheets, size);
}
/**
* Returns the {@link WaterMark}
*
* @return the {@link Workbook}
*/
public WaterMark getWaterMark() {
return waterMark;
}
/**
* Setting {@link WaterMark}
*
Use {@link WaterMark#of} method to create a water mark.
*
* @param waterMark the water mark
* @return the {@link Workbook}
*/
public Workbook setWaterMark(WaterMark waterMark) {
this.waterMark = waterMark;
return this;
}
/**
* Setting the database {@link Connection}
*
* EEC does not actively close the database connection,
* and needs to be manually closed externally. The {@link java.sql.Statement}
* and {@link ResultSet} generated inside this EEC will
* be actively closed.
*
* @param con the database connection
* @return the {@link Workbook}
*/
public Workbook setConnection(Connection con) {
this.con = con;
return this;
}
/**
* Setting auto-adjust the column width
*
* @param autoSize boolean value
* @return the {@link Workbook}
*/
public Workbook setAutoSize(boolean autoSize) {
this.autoSize = autoSize;
return this;
}
/**
* Returns whether to auto-adjust the column width
*
* @return true if auto-adjust the column width
*/
public boolean isAutoSize() {
return autoSize;
}
/**
* Returns the global {@link Styles}
*
* @return the Styles
*/
public Styles getStyles() {
return styles;
}
/**
* Setting the excel author name.
*
* If you do not set the creator it will get the current OS login user name,
* usually this is not a good idea. Applications are usually publish on server
* or cloud server, getting the system login user name doesn't make sense.
* If you don't want to set it and default setting the system login user name,
* you can set it to an empty string ("").
*
* Does anyone agree with this idea? If anyone agrees, I will consider removing
* this setting.
*
* @param creator the author name
* @return the {@link Workbook}
*/
public Workbook setCreator(String creator) {
this.creator = creator;
return this;
}
/**
* Setting the name of the company where the author is employed
*
* @param company the company name
* @return the {@link Workbook}
*/
public Workbook setCompany(String company) {
this.company = company;
return this;
}
/**
* Cancel the odd-fill style
*
* @return the {@link Workbook}
*/
public Workbook cancelOddFill() {
this.autoOdd = 1;
return this;
}
/**
* Setting the odd-fill style, default fill color is #E2EDDA
*
* @param fill the {@link Fill} style
* @return the {@link Workbook}
*/
public Workbook setOddFill(Fill fill) {
this.oddFill = fill;
return this;
}
/**
* Add a {@link Sheet} to the tail
*
* @param sheet a Worksheet
* @return the {@link Workbook}
*/
public Workbook addSheet(Sheet sheet) {
ensureCapacityInternal();
sheet.setWorkbook(this);
sheets[size++] = sheet;
return this;
}
/**
* Add a {@link ListSheet} to the tail with header {@link Sheet.Column} setting.
* Also you can use {@code addSheet(new ListSheet<>(data, columns)}
* to achieve the same effect.
*
* @param data List<?> data
* @param columns the header columns
* @return the {@link Workbook}
*/
public Workbook addSheet(List> data, Sheet.Column... columns) {
return addSheet(null, data, columns);
}
/**
* Add a {@link ListSheet} to the tail with Worksheet name
* and header {@link Sheet.Column} setting. Also you can use
* {@code addSheet(new ListSheet<>(name, data, columns)}
* to achieve the same effect.
*
* @param name the name of worksheet
* @param data List<?> data
* @param columns the header columns
* @return the {@link Workbook}
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public Workbook addSheet(String name, List> data, Sheet.Column... columns) {
Object o;
if (data == null || data.isEmpty() || (o = getFirst(data)) == null) {
addSheet(new EmptySheet(name, columns));
return this;
}
if (o instanceof Map) {
addSheet(new ListMapSheet(name, columns).setData((List