Browse Source

07版在导出的时候会导出 行数 #1282

pull/2074/head
Jiaju Zhuang 4 years ago
parent
commit
7c60a92483
  1. 49
      src/main/java/com/alibaba/excel/util/ClassUtils.java
  2. 94
      src/main/java/com/alibaba/excel/util/FieldUtils.java
  3. 54
      src/main/java/com/alibaba/excel/util/MemberUtils.java
  4. 25
      src/main/java/com/alibaba/excel/util/StringUtils.java
  5. 151
      src/main/java/com/alibaba/excel/util/Validate.java
  6. 5
      src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java
  7. 6
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java
  8. 14
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java
  9. 2
      src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java
  10. 6
      src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java
  11. 2
      src/main/java/com/alibaba/excel/write/handler/AbstractSheetWriteHandler.java
  12. 2
      src/main/java/com/alibaba/excel/write/handler/AbstractWorkbookWriteHandler.java
  13. 18
      src/main/java/com/alibaba/excel/write/handler/DefaultWriteHandlerLoader.java
  14. 43
      src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java
  15. 6
      src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java
  16. 22
      src/main/java/com/alibaba/excel/write/handler/impl/DefaultRowWriteHandler.java
  17. 76
      src/main/java/com/alibaba/excel/write/handler/impl/DimensionWorkbookWriteHandler.java
  18. 86
      src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java
  19. 3
      src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java

49
src/main/java/com/alibaba/excel/util/ClassUtils.java

@ -6,6 +6,8 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
@ -208,4 +210,51 @@ public class ClassUtils {
return ignoreMap; return ignoreMap;
} }
} }
/**
* <p>Gets a {@code List} of all interfaces implemented by the given
* class and its superclasses.</p>
*
* <p>The order is determined by looking through each interface in turn as
* declared in the source file and following its hierarchy up. Then each
* superclass is considered in the same way. Later duplicates are ignored,
* so the order is maintained.</p>
*
* @param cls the class to look up, may be {@code null}
* @return the {@code List} of interfaces in order,
* {@code null} if null input
*/
public static List<Class<?>> getAllInterfaces(final Class<?> cls) {
if (cls == null) {
return null;
}
final LinkedHashSet<Class<?>> interfacesFound = new LinkedHashSet<>();
getAllInterfaces(cls, interfacesFound);
return new ArrayList<>(interfacesFound);
}
/**
* Gets the interfaces for the specified class.
*
* @param cls the class to look up, may be {@code null}
* @param interfacesFound the {@code Set} of interfaces for the class
*/
private static void getAllInterfaces(Class<?> cls, final HashSet<Class<?>> interfacesFound) {
while (cls != null) {
final Class<?>[] interfaces = cls.getInterfaces();
for (final Class<?> i : interfaces) {
if (interfacesFound.add(i)) {
getAllInterfaces(i, interfacesFound);
}
}
cls = cls.getSuperclass();
}
}
} }

94
src/main/java/com/alibaba/excel/util/FieldUtils.java

@ -1,6 +1,8 @@
package com.alibaba.excel.util; package com.alibaba.excel.util;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/** /**
* Field utils * Field utils
@ -48,4 +50,96 @@ public class FieldUtils {
private static String buildFieldName(char firstChar, String fieldName) { private static String buildFieldName(char firstChar, String fieldName) {
return firstChar + fieldName.substring(1); return firstChar + fieldName.substring(1);
} }
/**
* Gets an accessible {@link Field} by name respecting scope. Superclasses/interfaces will be considered.
*
* @param cls
* the {@link Class} to reflect, must not be {@code null}
* @param fieldName
* the field name to obtain
* @return the Field object
* @throws IllegalArgumentException
* if the class is {@code null}, or the field name is blank or empty
*/
public static Field getField(final Class<?> cls, final String fieldName) {
final Field field = getField(cls, fieldName, false);
MemberUtils.setAccessibleWorkaround(field);
return field;
}
/**
* Gets an accessible {@link Field} by name, breaking scope if requested. Superclasses/interfaces will be
* considered.
*
* @param cls
* the {@link Class} to reflect, must not be {@code null}
* @param fieldName
* the field name to obtain
* @param forceAccess
* whether to break scope restrictions using the
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
* match {@code public} fields.
* @return the Field object
* @throws NullPointerException if the class is {@code null}
* @throws IllegalArgumentException if the field name is blank or empty or is matched at multiple places
* in the inheritance hierarchy
*/
public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
Validate.isTrue(cls != null, "The class must not be null");
Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty");
// FIXME is this workaround still needed? lang requires Java 6
// Sun Java 1.3 has a bugged implementation of getField hence we write the
// code ourselves
// getField() will return the Field object with the declaring class
// set correctly to the class that declares the field. Thus requesting the
// field on a subclass will return the field from the superclass.
//
// priority order for lookup:
// searchclass private/protected/package/public
// superclass protected/package/public
// private/different package blocks access to further superclasses
// implementedinterface public
// check up the superclass hierarchy
for (Class<?> acls = cls; acls != null; acls = acls.getSuperclass()) {
try {
final Field field = acls.getDeclaredField(fieldName);
// getDeclaredField checks for non-public scopes as well
// and it returns accurate results
if (!Modifier.isPublic(field.getModifiers())) {
if (forceAccess) {
field.setAccessible(true);
} else {
continue;
}
}
return field;
} catch (final NoSuchFieldException ex) { // NOPMD
// ignore
}
}
// check the public interface case. This must be manually searched for
// incase there is a public supersuperclass field hidden by a private/package
// superclass field.
Field match = null;
for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) {
try {
final Field test = class1.getField(fieldName);
Validate.isTrue(match == null, "Reference to field %s is ambiguous relative to %s"
+ "; a matching field exists on two or more implemented interfaces.", fieldName, cls);
match = test;
} catch (final NoSuchFieldException ex) { // NOPMD
// ignore
}
}
return match;
}
} }

54
src/main/java/com/alibaba/excel/util/MemberUtils.java

@ -0,0 +1,54 @@
package com.alibaba.excel.util;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
/**
* Member utils.
*
* @author Jiaju Zhuang
*/
public class MemberUtils {
private static final int ACCESS_TEST = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE;
/**
* XXX Default access superclass workaround.
*
* When a {@code public} class has a default access superclass with {@code public} members,
* these members are accessible. Calling them from compiled code works fine.
* Unfortunately, on some JVMs, using reflection to invoke these members
* seems to (wrongly) prevent access even when the modifier is {@code public}.
* Calling {@code setAccessible(true)} solves the problem but will only work from
* sufficiently privileged code. Better workarounds would be gratefully
* accepted.
* @param o the AccessibleObject to set as accessible
* @return a boolean indicating whether the accessibility of the object was set to true.
*/
static boolean setAccessibleWorkaround(final AccessibleObject o) {
if (o == null || o.isAccessible()) {
return false;
}
final Member m = (Member) o;
if (!o.isAccessible() && Modifier.isPublic(m.getModifiers()) && isPackageAccess(m.getDeclaringClass().getModifiers())) {
try {
o.setAccessible(true);
return true;
} catch (final SecurityException e) { // NOPMD
// ignore in favor of subsequent IllegalAccessException
}
}
return false;
}
/**
* Returns whether a given set of modifiers implies package access.
* @param modifiers to test
* @return {@code true} unless {@code package}/{@code protected}/{@code private} modifier detected
*/
static boolean isPackageAccess(final int modifiers) {
return (modifiers & ACCESS_TEST) == 0;
}
}

25
src/main/java/com/alibaba/excel/util/StringUtils.java

@ -69,4 +69,29 @@ public class StringUtils {
return true; return true;
} }
/**
* <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
*
* <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
*
* <pre>
* StringUtils.isNotBlank(null) = false
* StringUtils.isNotBlank("") = false
* StringUtils.isNotBlank(" ") = false
* StringUtils.isNotBlank("bob") = true
* StringUtils.isNotBlank(" bob ") = true
* </pre>
*
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is
* not empty and not null and not whitespace only
* @since 2.0
* @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
*/
public static boolean isNotBlank(final CharSequence cs) {
return !isBlank(cs);
}
} }

151
src/main/java/com/alibaba/excel/util/Validate.java

@ -0,0 +1,151 @@
package com.alibaba.excel.util;
import java.util.Objects;
/**
* Validate
*
* @author Jiaju Zhuang
*/
public class Validate {
private static final String DEFAULT_IS_TRUE_EX_MESSAGE = "The validated expression is false";
private static final String DEFAULT_IS_NULL_EX_MESSAGE = "The validated object is null";
/**
* <p>Validate that the argument condition is {@code true}; otherwise
* throwing an exception with the specified message. This method is useful when
* validating according to an arbitrary boolean expression, such as validating a
* primitive number or using your own custom validation expression.</p>
*
* <pre>Validate.isTrue(i &gt; 0.0, "The value must be greater than zero: &#37;d", i);</pre>
*
* <p>For performance reasons, the long value is passed as a separate parameter and
* appended to the exception message only in the case of an error.</p>
*
* @param expression the boolean expression to check
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
* @param value the value to append to the message when invalid
* @throws IllegalArgumentException if expression is {@code false}
* @see #isTrue(boolean)
* @see #isTrue(boolean, String, double)
* @see #isTrue(boolean, String, Object...)
*/
public static void isTrue(final boolean expression, final String message, final long value) {
if (!expression) {
throw new IllegalArgumentException(String.format(message, Long.valueOf(value)));
}
}
/**
* <p>Validate that the argument condition is {@code true}; otherwise
* throwing an exception with the specified message. This method is useful when
* validating according to an arbitrary boolean expression, such as validating a
* primitive number or using your own custom validation expression.</p>
*
* <pre>Validate.isTrue(d &gt; 0.0, "The value must be greater than zero: &#37;s", d);</pre>
*
* <p>For performance reasons, the double value is passed as a separate parameter and
* appended to the exception message only in the case of an error.</p>
*
* @param expression the boolean expression to check
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
* @param value the value to append to the message when invalid
* @throws IllegalArgumentException if expression is {@code false}
* @see #isTrue(boolean)
* @see #isTrue(boolean, String, long)
* @see #isTrue(boolean, String, Object...)
*/
public static void isTrue(final boolean expression, final String message, final double value) {
if (!expression) {
throw new IllegalArgumentException(String.format(message, Double.valueOf(value)));
}
}
/**
* <p>Validate that the argument condition is {@code true}; otherwise
* throwing an exception with the specified message. This method is useful when
* validating according to an arbitrary boolean expression, such as validating a
* primitive number or using your own custom validation expression.</p>
*
* <pre>
* Validate.isTrue(i &gt;= min &amp;&amp; i &lt;= max, "The value must be between &#37;d and &#37;d", min, max);
* Validate.isTrue(myObject.isOk(), "The object is not okay");</pre>
*
* @param expression the boolean expression to check
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
* @param values the optional values for the formatted exception message, null array not recommended
* @throws IllegalArgumentException if expression is {@code false}
* @see #isTrue(boolean)
* @see #isTrue(boolean, String, long)
* @see #isTrue(boolean, String, double)
*/
public static void isTrue(final boolean expression, final String message, final Object... values) {
if (!expression) {
throw new IllegalArgumentException(String.format(message, values));
}
}
/**
* <p>Validate that the argument condition is {@code true}; otherwise
* throwing an exception. This method is useful when validating according
* to an arbitrary boolean expression, such as validating a
* primitive number or using your own custom validation expression.</p>
*
* <pre>
* Validate.isTrue(i &gt; 0);
* Validate.isTrue(myObject.isOk());</pre>
*
* <p>The message of the exception is &quot;The validated expression is
* false&quot;.</p>
*
* @param expression the boolean expression to check
* @throws IllegalArgumentException if expression is {@code false}
* @see #isTrue(boolean, String, long)
* @see #isTrue(boolean, String, double)
* @see #isTrue(boolean, String, Object...)
*/
public static void isTrue(final boolean expression) {
if (!expression) {
throw new IllegalArgumentException(DEFAULT_IS_TRUE_EX_MESSAGE);
}
}
/**
* <p>Validate that the specified argument is not {@code null};
* otherwise throwing an exception.
*
* <pre>Validate.notNull(myObject, "The object must not be null");</pre>
*
* <p>The message of the exception is &quot;The validated object is
* null&quot;.</p>
*
* @param <T> the object type
* @param object the object to check
* @return the validated object (never {@code null} for method chaining)
* @throws NullPointerException if the object is {@code null}
* @see #notNull(Object, String, Object...)
*/
public static <T> T notNull(final T object) {
return notNull(object, DEFAULT_IS_NULL_EX_MESSAGE);
}
/**
* <p>Validate that the specified argument is not {@code null};
* otherwise throwing an exception with the specified message.
*
* <pre>Validate.notNull(myObject, "The object must not be null");</pre>
*
* @param <T> the object type
* @param object the object to check
* @param message the {@link String#format(String, Object...)} exception message if invalid, not null
* @param values the optional values for the formatted exception message
* @return the validated object (never {@code null} for method chaining)
* @throws NullPointerException if the object is {@code null}
* @see #notNull(Object)
*/
public static <T> T notNull(final T object, final String message, final Object... values) {
return Objects.requireNonNull(object, () -> String.format(message, values));
}
}

5
src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java

@ -1,13 +1,18 @@
package com.alibaba.excel.write; package com.alibaba.excel.write;
import java.lang.reflect.Field;
import java.util.List; import java.util.List;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.context.WriteContextImpl; import com.alibaba.excel.context.WriteContextImpl;
import com.alibaba.excel.enums.WriteTypeEnum; import com.alibaba.excel.enums.WriteTypeEnum;
import com.alibaba.excel.exception.ExcelGenerateException; import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.util.FieldUtils;
import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.write.executor.ExcelWriteAddExecutor; import com.alibaba.excel.write.executor.ExcelWriteAddExecutor;
import com.alibaba.excel.write.executor.ExcelWriteFillExecutor; import com.alibaba.excel.write.executor.ExcelWriteFillExecutor;

6
src/main/java/com/alibaba/excel/write/executor/ExcelWriteAddExecutor.java

@ -49,9 +49,10 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
// BeanMap is out of order,so use sortedAllFiledMap // BeanMap is out of order,so use sortedAllFiledMap
Map<Integer, Field> sortedAllFiledMap = new TreeMap<Integer, Field>(); Map<Integer, Field> sortedAllFiledMap = new TreeMap<Integer, Field>();
int relativeRowIndex = 0; int relativeRowIndex = 0;
int lastRowIndex = 0;
for (Object oneRowData : data) { for (Object oneRowData : data) {
int n = relativeRowIndex + newRowIndex; lastRowIndex = relativeRowIndex + newRowIndex;
addOneRowOfDataToExcel(oneRowData, n, relativeRowIndex, sortedAllFiledMap); addOneRowOfDataToExcel(oneRowData, lastRowIndex, relativeRowIndex, sortedAllFiledMap);
relativeRowIndex++; relativeRowIndex++;
} }
} }
@ -108,6 +109,7 @@ public class ExcelWriteAddExecutor extends AbstractExcelWriteExecutor {
Object value = oneRowData.get(dataIndex); Object value = oneRowData.get(dataIndex);
CellData cellData = converterAndSet(writeContext.currentWriteHolder(), value == null ? null : value.getClass(), CellData cellData = converterAndSet(writeContext.currentWriteHolder(), value == null ? null : value.getClass(),
cell, value, null, head, relativeRowIndex); cell, value, null, head, relativeRowIndex);
writeContext.writeSheetHolder().setLastRowIndex(cellData.getRowIndex());
WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE);
} }

14
src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java

@ -93,7 +93,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
Object realData; Object realData;
if (data instanceof FillWrapper) { if (data instanceof FillWrapper) {
FillWrapper fillWrapper = (FillWrapper) data; FillWrapper fillWrapper = (FillWrapper)data;
currentDataPrefix = fillWrapper.getName(); currentDataPrefix = fillWrapper.getName();
realData = fillWrapper.getCollectionData(); realData = fillWrapper.getCollectionData();
} else { } else {
@ -105,7 +105,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
// processing data // processing data
if (realData instanceof Collection) { if (realData instanceof Collection) {
List<AnalysisCell> analysisCellList = readTemplateData(templateCollectionAnalysisCache); List<AnalysisCell> analysisCellList = readTemplateData(templateCollectionAnalysisCache);
Collection collectionData = (Collection) realData; Collection collectionData = (Collection)realData;
if (CollectionUtils.isEmpty(collectionData)) { if (CollectionUtils.isEmpty(collectionData)) {
return; return;
} }
@ -183,7 +183,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
} }
Map dataMap; Map dataMap;
if (oneRowData instanceof Map) { if (oneRowData instanceof Map) {
dataMap = (Map) oneRowData; dataMap = (Map)oneRowData;
} else { } else {
dataMap = BeanMap.create(oneRowData); dataMap = BeanMap.create(oneRowData);
} }
@ -293,7 +293,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
} }
Row row = createRowIfNecessary(sheet, cachedSheet, lastRowIndex, fillConfig, analysisCell, isOriginalCell); Row row = createRowIfNecessary(sheet, cachedSheet, lastRowIndex, fillConfig, analysisCell, isOriginalCell);
Cell cell = createCellIfNecessary(row,lastColumnIndex); Cell cell = createCellIfNecessary(row, lastColumnIndex);
Map<AnalysisCell, CellStyle> collectionFieldStyleMap = collectionFieldStyleCache.get(currentUniqueDataFlag); Map<AnalysisCell, CellStyle> collectionFieldStyleMap = collectionFieldStyleCache.get(currentUniqueDataFlag);
if (collectionFieldStyleMap == null) { if (collectionFieldStyleMap == null) {
@ -335,7 +335,8 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
row = cachedSheet.createRow(lastRowIndex); row = cachedSheet.createRow(lastRowIndex);
} else { } else {
// The last row of the middle disk inside empty rows, resulting in cachedSheet can not get inside. // The last row of the middle disk inside empty rows, resulting in cachedSheet can not get inside.
// Will throw Attempting to write a row[" + rownum + "] " + "in the range [0," + this._sh.getLastRowNum() + "] that is already written to disk. // Will throw Attempting to write a row[" + rownum + "] " + "in the range [0," + this._sh
// .getLastRowNum() + "] that is already written to disk.
try { try {
row = sheet.createRow(lastRowIndex); row = sheet.createRow(lastRowIndex);
} catch (IllegalArgumentException ignore) { } catch (IllegalArgumentException ignore) {
@ -414,7 +415,8 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
int startIndex = 0; int startIndex = 0;
int length = value.length(); int length = value.length();
int lastPrepareDataIndex = 0; int lastPrepareDataIndex = 0;
out: while (startIndex < length) { out:
while (startIndex < length) {
int prefixIndex = value.indexOf(FILL_PREFIX, startIndex); int prefixIndex = value.indexOf(FILL_PREFIX, startIndex);
if (prefixIndex < 0) { if (prefixIndex < 0) {
break out; break out;

2
src/main/java/com/alibaba/excel/write/handler/AbstractCellWriteHandler.java

@ -14,7 +14,9 @@ import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
* Abstract cell write handler * Abstract cell write handler
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
* @deprecated Please use it directly {@link CellWriteHandler}
**/ **/
@Deprecated
public abstract class AbstractCellWriteHandler implements CellWriteHandler { public abstract class AbstractCellWriteHandler implements CellWriteHandler {
@Override @Override

6
src/main/java/com/alibaba/excel/write/handler/AbstractRowWriteHandler.java

@ -1,15 +1,17 @@
package com.alibaba.excel.write.handler; package com.alibaba.excel.write.handler;
import org.apache.poi.ss.usermodel.Row;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Row;
/** /**
* Abstract row write handler * Abstract row write handler
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
* @deprecated Please use it directly {@link RowWriteHandler}
**/ **/
@Deprecated
public abstract class AbstractRowWriteHandler implements RowWriteHandler { public abstract class AbstractRowWriteHandler implements RowWriteHandler {
@Override @Override
public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,

2
src/main/java/com/alibaba/excel/write/handler/AbstractSheetWriteHandler.java

@ -7,7 +7,9 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
* Abstract sheet write handler * Abstract sheet write handler
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
* @deprecated Please use it directly {@link SheetWriteHandler}
**/ **/
@Deprecated
public abstract class AbstractSheetWriteHandler implements SheetWriteHandler { public abstract class AbstractSheetWriteHandler implements SheetWriteHandler {
@Override @Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {

2
src/main/java/com/alibaba/excel/write/handler/AbstractWorkbookWriteHandler.java

@ -6,7 +6,9 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
* Abstract workbook write handler * Abstract workbook write handler
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
* @deprecated Please use it directly {@link WorkbookWriteHandler}
**/ **/
@Deprecated
public abstract class AbstractWorkbookWriteHandler implements WorkbookWriteHandler { public abstract class AbstractWorkbookWriteHandler implements WorkbookWriteHandler {
@Override @Override

18
src/main/java/com/alibaba/excel/write/handler/DefaultWriteHandlerLoader.java

@ -3,12 +3,14 @@ package com.alibaba.excel.write.handler;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.poi.ss.usermodel.IndexedColors; import com.alibaba.excel.write.handler.impl.DefaultRowWriteHandler;
import com.alibaba.excel.write.handler.impl.DimensionWorkbookWriteHandler;
import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.IndexedColors;
/** /**
* Load default handler * Load default handler
* *
@ -16,13 +18,20 @@ import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
*/ */
public class DefaultWriteHandlerLoader { public class DefaultWriteHandlerLoader {
public static final List<WriteHandler> DEFAULT_WRITE_HANDLER_LIST = new ArrayList<>();
static {
DEFAULT_WRITE_HANDLER_LIST.add(new DimensionWorkbookWriteHandler());
DEFAULT_WRITE_HANDLER_LIST.add(new DefaultRowWriteHandler());
}
/** /**
* Load default handler * Load default handler
* *
* @return * @return
*/ */
public static List<WriteHandler> loadDefaultHandler(Boolean useDefaultStyle) { public static List<WriteHandler> loadDefaultHandler(Boolean useDefaultStyle) {
List<WriteHandler> handlerList = new ArrayList<WriteHandler>(); List<WriteHandler> handlerList = new ArrayList<>();
if (useDefaultStyle) { if (useDefaultStyle) {
WriteCellStyle headWriteCellStyle = new WriteCellStyle(); WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
@ -31,8 +40,9 @@ public class DefaultWriteHandlerLoader {
headWriteFont.setFontHeightInPoints((short)14); headWriteFont.setFontHeightInPoints((short)14);
headWriteFont.setBold(true); headWriteFont.setBold(true);
headWriteCellStyle.setWriteFont(headWriteFont); headWriteCellStyle.setWriteFont(headWriteFont);
handlerList.add(new HorizontalCellStyleStrategy(headWriteCellStyle, new ArrayList<WriteCellStyle>())); handlerList.add(new HorizontalCellStyleStrategy(headWriteCellStyle, new ArrayList<>()));
} }
handlerList.addAll(DEFAULT_WRITE_HANDLER_LIST);
return handlerList; return handlerList;
} }

43
src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java

@ -1,10 +1,10 @@
package com.alibaba.excel.write.handler; package com.alibaba.excel.write.handler;
import org.apache.poi.ss.usermodel.Row;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Row;
/** /**
* intercepts handle row creation * intercepts handle row creation
* *
@ -16,44 +16,35 @@ public interface RowWriteHandler extends WriteHandler {
* Called before create the row * Called before create the row
* *
* @param writeSheetHolder * @param writeSheetHolder
* @param writeTableHolder * @param writeTableHolder Nullable.It is null without using table writes.
* Nullable.It is null without using table writes.
* @param rowIndex * @param rowIndex
* @param relativeRowIndex * @param relativeRowIndex Nullable.It is null in the case of fill data.
* Nullable.It is null in the case of fill data. * @param isHead Nullable.It is null in the case of fill data.
* @param isHead
* Nullable.It is null in the case of fill data.
*/ */
void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, default void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex,
Integer relativeRowIndex, Boolean isHead); Integer relativeRowIndex, Boolean isHead) {}
/** /**
* Called after the row is created * Called after the row is created
* *
* @param writeSheetHolder * @param writeSheetHolder
* @param writeTableHolder * @param writeTableHolder Nullable.It is null without using table writes.
* Nullable.It is null without using table writes.
* @param row * @param row
* @param relativeRowIndex * @param relativeRowIndex Nullable.It is null in the case of fill data.
* Nullable.It is null in the case of fill data. * @param isHead Nullable.It is null in the case of fill data.
* @param isHead
* Nullable.It is null in the case of fill data.
*/ */
void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, default void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead); Integer relativeRowIndex, Boolean isHead) {}
/** /**
* Called after all operations on the row have been completed.This method is not called when fill the data. * Called after all operations on the row have been completed.This method is not called when fill the data.
* *
* @param writeSheetHolder * @param writeSheetHolder
* @param writeTableHolder * @param writeTableHolder Nullable.It is null without using table writes.
* Nullable.It is null without using table writes.
* @param row * @param row
* @param relativeRowIndex * @param relativeRowIndex Nullable.It is null in the case of fill data.
* Nullable.It is null in the case of fill data. * @param isHead Nullable.It is null in the case of fill data.
* @param isHead
* Nullable.It is null in the case of fill data.
*/ */
void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, default void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead); Integer relativeRowIndex, Boolean isHead) {}
} }

6
src/main/java/com/alibaba/excel/write/handler/WorkbookWriteHandler.java

@ -12,19 +12,19 @@ public interface WorkbookWriteHandler extends WriteHandler {
/** /**
* Called before create the workbook * Called before create the workbook
*/ */
void beforeWorkbookCreate(); default void beforeWorkbookCreate() {}
/** /**
* Called after the workbook is created * Called after the workbook is created
* *
* @param writeWorkbookHolder * @param writeWorkbookHolder
*/ */
void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder); default void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {}
/** /**
* Called after all operations on the workbook have been completed * Called after all operations on the workbook have been completed
* *
* @param writeWorkbookHolder * @param writeWorkbookHolder
*/ */
void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder); default void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {}
} }

22
src/main/java/com/alibaba/excel/write/handler/impl/DefaultRowWriteHandler.java

@ -0,0 +1,22 @@
package com.alibaba.excel.write.handler.impl;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
/**
* Default row handler.
*
* @author Jiaju Zhuang
*/
@Slf4j
public class DefaultRowWriteHandler implements RowWriteHandler {
@Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead) {
writeSheetHolder.setLastRowIndex(row.getRowNum());
}
}

76
src/main/java/com/alibaba/excel/write/handler/impl/DimensionWorkbookWriteHandler.java

@ -0,0 +1,76 @@
package com.alibaba.excel.write.handler.impl;
import java.lang.reflect.Field;
import java.util.Map;
import com.alibaba.excel.util.FieldUtils;
import com.alibaba.excel.write.handler.WorkbookWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
/**
* Handle the problem of unable to write dimension.
*
* https://github.com/alibaba/easyexcel/issues/1282
*
* @author Jiaju Zhuang
*/
@Slf4j
public class DimensionWorkbookWriteHandler implements WorkbookWriteHandler {
private static final String XSSF_SHEET_MEMBER_VARIABLE_NAME = "_sh";
private static final Field XSSF_SHEET_FIELD = FieldUtils.getField(SXSSFSheet.class, XSSF_SHEET_MEMBER_VARIABLE_NAME,
true);
@Override
public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {
if (writeWorkbookHolder == null || writeWorkbookHolder.getWorkbook() == null) {
return;
}
if (!(writeWorkbookHolder.getWorkbook() instanceof SXSSFWorkbook)) {
return;
}
Map<Integer, WriteSheetHolder> writeSheetHolderMap = writeWorkbookHolder.getHasBeenInitializedSheetIndexMap();
if (MapUtils.isEmpty(writeSheetHolderMap)) {
return;
}
for (WriteSheetHolder writeSheetHolder : writeSheetHolderMap.values()) {
if (writeSheetHolder.getSheet() == null || !(writeSheetHolder.getSheet() instanceof SXSSFSheet)) {
continue;
}
SXSSFSheet sxssfSheet = ((SXSSFSheet)writeSheetHolder.getSheet());
XSSFSheet xssfSheet;
try {
xssfSheet = (XSSFSheet)XSSF_SHEET_FIELD.get(sxssfSheet);
} catch (IllegalAccessException e) {
log.debug("Can not found _sh.", e);
continue;
}
if (xssfSheet == null) {
continue;
}
CTWorksheet ctWorksheet = xssfSheet.getCTWorksheet();
if (ctWorksheet == null) {
continue;
}
int headSize = 0;
if (MapUtils.isNotEmpty(writeSheetHolder.getExcelWriteHeadProperty().getHeadMap())) {
headSize = writeSheetHolder.getExcelWriteHeadProperty().getHeadMap().size();
if (headSize > 0) {
headSize--;
}
}
ctWorksheet.getDimension().setRef(
"A1:" + CellReference.convertNumToColString(headSize) + (writeSheetHolder.getLastRowIndex() + 1));
}
}
}

86
src/main/java/com/alibaba/excel/write/metadata/holder/WriteSheetHolder.java

@ -3,21 +3,25 @@ package com.alibaba.excel.write.metadata.holder;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import com.alibaba.excel.enums.HolderEnum; import com.alibaba.excel.enums.HolderEnum;
import com.alibaba.excel.enums.WriteLastRowTypeEnum; import com.alibaba.excel.enums.WriteLastRowTypeEnum;
import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.Getter;
import lombok.Setter;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
/** /**
* sheet holder * sheet holder
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Getter
@Setter
public class WriteSheetHolder extends AbstractWriteHolder { public class WriteSheetHolder extends AbstractWriteHolder {
/** /**
* current param * current param
@ -65,6 +69,11 @@ public class WriteSheetHolder extends AbstractWriteHolder {
*/ */
private WriteLastRowTypeEnum writeLastRowTypeEnum; private WriteLastRowTypeEnum writeLastRowTypeEnum;
/**
* last row index
*/
private Integer lastRowIndex;
public WriteSheetHolder(WriteSheet writeSheet, WriteWorkbookHolder writeWorkbookHolder) { public WriteSheetHolder(WriteSheet writeSheet, WriteWorkbookHolder writeWorkbookHolder) {
super(writeSheet, writeWorkbookHolder, writeWorkbookHolder.getWriteWorkbook().getConvertAllFiled()); super(writeSheet, writeWorkbookHolder, writeWorkbookHolder.getWriteWorkbook().getConvertAllFiled());
this.writeSheet = writeSheet; this.writeSheet = writeSheet;
@ -75,76 +84,13 @@ public class WriteSheetHolder extends AbstractWriteHolder {
} }
this.sheetName = writeSheet.getSheetName(); this.sheetName = writeSheet.getSheetName();
this.parentWriteWorkbookHolder = writeWorkbookHolder; this.parentWriteWorkbookHolder = writeWorkbookHolder;
this.hasBeenInitializedTable = new HashMap<Integer, WriteTableHolder>(); this.hasBeenInitializedTable = new HashMap<>();
if (writeWorkbookHolder.getTempTemplateInputStream() != null) { if (writeWorkbookHolder.getTempTemplateInputStream() != null) {
writeLastRowTypeEnum = WriteLastRowTypeEnum.TEMPLATE_EMPTY; writeLastRowTypeEnum = WriteLastRowTypeEnum.TEMPLATE_EMPTY;
} else { } else {
writeLastRowTypeEnum = WriteLastRowTypeEnum.COMMON_EMPTY; writeLastRowTypeEnum = WriteLastRowTypeEnum.COMMON_EMPTY;
} }
} lastRowIndex = 0;
public WriteSheet getWriteSheet() {
return writeSheet;
}
public void setWriteSheet(WriteSheet writeSheet) {
this.writeSheet = writeSheet;
}
public Sheet getSheet() {
return sheet;
}
public void setSheet(Sheet sheet) {
this.sheet = sheet;
}
public Integer getSheetNo() {
return sheetNo;
}
public Sheet getCachedSheet() {
return cachedSheet;
}
public void setCachedSheet(Sheet cachedSheet) {
this.cachedSheet = cachedSheet;
}
public void setSheetNo(Integer sheetNo) {
this.sheetNo = sheetNo;
}
public String getSheetName() {
return sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public WriteWorkbookHolder getParentWriteWorkbookHolder() {
return parentWriteWorkbookHolder;
}
public void setParentWriteWorkbookHolder(WriteWorkbookHolder parentWriteWorkbookHolder) {
this.parentWriteWorkbookHolder = parentWriteWorkbookHolder;
}
public Map<Integer, WriteTableHolder> getHasBeenInitializedTable() {
return hasBeenInitializedTable;
}
public void setHasBeenInitializedTable(Map<Integer, WriteTableHolder> hasBeenInitializedTable) {
this.hasBeenInitializedTable = hasBeenInitializedTable;
}
public WriteLastRowTypeEnum getWriteLastRowTypeEnum() {
return writeLastRowTypeEnum;
}
public void setWriteLastRowTypeEnum(WriteLastRowTypeEnum writeLastRowTypeEnum) {
this.writeLastRowTypeEnum = writeLastRowTypeEnum;
} }
/** /**

3
src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java

@ -14,6 +14,7 @@ import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.beans.BeanMap; import net.sf.cglib.beans.BeanMap;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -26,6 +27,7 @@ import org.slf4j.LoggerFactory;
* @author Jiaju Zhuang * @author Jiaju Zhuang
**/ **/
@Ignore @Ignore
@Slf4j
public class Wirte { public class Wirte {
private static final Logger LOGGER = LoggerFactory.getLogger(Wirte.class); private static final Logger LOGGER = LoggerFactory.getLogger(Wirte.class);
@ -42,6 +44,7 @@ public class Wirte {
@Test @Test
public void simpleWrite() { public void simpleWrite() {
log.info("t5");
// 写法1 // 写法1
String fileName = TestFileUtil.getPath() + "t22" + System.currentTimeMillis() + ".xlsx"; String fileName = TestFileUtil.getPath() + "t22" + System.currentTimeMillis() + ".xlsx";
// 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭

Loading…
Cancel
Save