forked from fanruan/easyexcel
Jiaju Zhuang
4 years ago
19 changed files with 551 additions and 113 deletions
@ -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; |
||||
} |
||||
} |
@ -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 > 0.0, "The value must be greater than zero: %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 > 0.0, "The value must be greater than zero: %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 >= min && i <= max, "The value must be between %d and %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 > 0); |
||||
* Validate.isTrue(myObject.isOk());</pre> |
||||
* |
||||
* <p>The message of the exception is "The validated expression is |
||||
* false".</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 "The validated object is |
||||
* null".</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)); |
||||
} |
||||
} |
@ -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()); |
||||
} |
||||
} |
@ -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)); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue