Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.fesod.sheet.annotation.write.style;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* An annotation used to define a freeze pane for an Excel sheet.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface FreezePane {

/**
* Horizontal position of split.
*/
int colSplit() default 0;

/**
* Vertical position of split.
*/
int rowSplit() default 0;

/**
* Left column visible in right pane. By default, it's equal to colSplit.
*/
int leftmostColumn() default -1;

/**
* Top row visible in bottom pane. By default, it's equal to rowSplit.
*/
int topRow() default -1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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.fesod.sheet.metadata.property;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.apache.fesod.sheet.annotation.write.style.FreezePane;

/**
* Property configuration for an Excel sheet freeze pane.
* <p>
* This class holds the configuration details required to create a freeze pane.
* It is typically built from the {@link FreezePane} annotation.
*/
@Getter
@Setter
@EqualsAndHashCode
public class SheetFreezePaneProperty {

/**
* Horizontal position of split.
*/
private int colSplit;

/**
* Vertical position of split.
*/
private int rowSplit;

/**
* Left column visible in right pane.
*/
private int leftmostColumn;

/**
* Top row visible in bottom pane
*/
private int topRow;

public static SheetFreezePaneProperty build(FreezePane freezePane) {
if (freezePane == null) {
return null;
}
SheetFreezePaneProperty result = new SheetFreezePaneProperty();
result.setColSplit(freezePane.colSplit());
result.setRowSplit(freezePane.rowSplit());
result.setLeftmostColumn(getOrDefault(freezePane.leftmostColumn(), freezePane.colSplit()));
result.setTopRow(getOrDefault(freezePane.topRow(), freezePane.rowSplit()));
return result;
}

private static Integer getOrDefault(Integer value, Integer defaultValue) {
if (value == -1) {
return defaultValue;
}
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.apache.fesod.sheet.metadata.property.LoopMergeProperty;
import org.apache.fesod.sheet.metadata.property.OnceAbsoluteMergeProperty;
import org.apache.fesod.sheet.metadata.property.RowHeightProperty;
import org.apache.fesod.sheet.metadata.property.SheetFreezePaneProperty;
import org.apache.fesod.sheet.write.handler.CellWriteHandler;
import org.apache.fesod.sheet.write.handler.DefaultWriteHandlerLoader;
import org.apache.fesod.sheet.write.handler.RowWriteHandler;
Expand All @@ -68,6 +69,7 @@
import org.apache.fesod.sheet.write.metadata.style.WriteCellStyle;
import org.apache.fesod.sheet.write.property.ExcelWriteHeadProperty;
import org.apache.fesod.sheet.write.style.AbstractVerticalCellStyleStrategy;
import org.apache.fesod.sheet.write.style.SheetFreezePaneStrategy;
import org.apache.fesod.sheet.write.style.column.AbstractHeadColumnWidthStyleStrategy;
import org.apache.fesod.sheet.write.style.row.SimpleRowHeightStyleStrategy;

Expand Down Expand Up @@ -342,6 +344,7 @@ protected void initAnnotationConfig(List<WriteHandler> handlerList, WriteBasicPa
dealStyle(handlerList);
dealRowHigh(handlerList);
dealOnceAbsoluteMerge(handlerList);
dealSheetFreezePane(handlerList);
}

private void dealStyle(List<WriteHandler> handlerList) {
Expand Down Expand Up @@ -387,6 +390,14 @@ private void dealOnceAbsoluteMerge(List<WriteHandler> handlerList) {
handlerList.add(new OnceAbsoluteMergeStrategy(onceAbsoluteMergeProperty));
}

private void dealSheetFreezePane(List<WriteHandler> handlerList) {
SheetFreezePaneProperty freezePaneProperty = getExcelWriteHeadProperty().getFreezePaneProperty();
if (freezePaneProperty == null) {
return;
}
handlerList.add(new SheetFreezePaneStrategy(freezePaneProperty));
}

private void dealRowHigh(List<WriteHandler> handlerList) {
RowHeightProperty headRowHeightProperty = getExcelWriteHeadProperty().getHeadRowHeightProperty();
RowHeightProperty contentRowHeightProperty = getExcelWriteHeadProperty().getContentRowHeightProperty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.apache.fesod.sheet.annotation.write.style.ColumnWidth;
import org.apache.fesod.sheet.annotation.write.style.ContentLoopMerge;
import org.apache.fesod.sheet.annotation.write.style.ContentRowHeight;
import org.apache.fesod.sheet.annotation.write.style.FreezePane;
import org.apache.fesod.sheet.annotation.write.style.HeadFontStyle;
import org.apache.fesod.sheet.annotation.write.style.HeadRowHeight;
import org.apache.fesod.sheet.annotation.write.style.HeadStyle;
Expand All @@ -53,6 +54,7 @@
import org.apache.fesod.sheet.metadata.property.LoopMergeProperty;
import org.apache.fesod.sheet.metadata.property.OnceAbsoluteMergeProperty;
import org.apache.fesod.sheet.metadata.property.RowHeightProperty;
import org.apache.fesod.sheet.metadata.property.SheetFreezePaneProperty;
import org.apache.fesod.sheet.metadata.property.StyleProperty;

/**
Expand All @@ -67,6 +69,7 @@ public class ExcelWriteHeadProperty extends ExcelHeadProperty {
private RowHeightProperty headRowHeightProperty;
private RowHeightProperty contentRowHeightProperty;
private OnceAbsoluteMergeProperty onceAbsoluteMergeProperty;
private SheetFreezePaneProperty freezePaneProperty;

public ExcelWriteHeadProperty(
ConfigurationHolder configurationHolder, Class<?> headClazz, List<List<String>> head) {
Expand All @@ -78,6 +81,7 @@ public ExcelWriteHeadProperty(
this.contentRowHeightProperty = RowHeightProperty.build(headClazz.getAnnotation(ContentRowHeight.class));
this.onceAbsoluteMergeProperty =
OnceAbsoluteMergeProperty.build(headClazz.getAnnotation(OnceAbsoluteMerge.class));
this.freezePaneProperty = SheetFreezePaneProperty.build(headClazz.getAnnotation(FreezePane.class));

ColumnWidth parentColumnWidth = headClazz.getAnnotation(ColumnWidth.class);
HeadStyle parentHeadStyle = headClazz.getAnnotation(HeadStyle.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* 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.fesod.sheet.write.style;

import org.apache.fesod.common.util.ValidateUtils;
import org.apache.fesod.sheet.metadata.property.SheetFreezePaneProperty;
import org.apache.fesod.sheet.write.handler.SheetWriteHandler;
import org.apache.fesod.sheet.write.metadata.holder.WriteSheetHolder;
import org.apache.fesod.sheet.write.metadata.holder.WriteWorkbookHolder;

/**
* A strategy for creating a freeze pane. Any existing freeze pane or split pane is overwritten.
*/
public class SheetFreezePaneStrategy implements SheetWriteHandler {

/**
* Horizontal position of split.
*/
private final int colSplit;

/**
* Vertical position of split.
*/
private final int rowSplit;

/**
* Left column visible in right pane.
*/
private final int leftmostColumn;

/**
* Top row visible in bottom pane
*/
private final int topRow;

public SheetFreezePaneStrategy(SheetFreezePaneProperty property) {
this(property.getColSplit(), property.getRowSplit(), property.getLeftmostColumn(), property.getTopRow());
}

public SheetFreezePaneStrategy(int colSplit, int rowSplit) {
this(colSplit, rowSplit, colSplit, rowSplit);
}

public SheetFreezePaneStrategy(int colSplit, int rowSplit, int leftmostColumn, int topRow) {
ValidateUtils.isTrue(colSplit >= 0, "colSplit must be >= 0");
ValidateUtils.isTrue(rowSplit >= 0, "rowSplit must be >= 0");
ValidateUtils.isTrue(leftmostColumn >= 0, "leftmostColumn must be >= 0");
ValidateUtils.isTrue(topRow >= 0, "topRow must be >= 0");

this.colSplit = colSplit;
this.rowSplit = rowSplit;
this.leftmostColumn = leftmostColumn;
this.topRow = topRow;
}

@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
writeSheetHolder.getSheet().createFreezePane(colSplit, rowSplit, leftmostColumn, topRow);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 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.fesod.sheet.metadata.property;

import org.apache.fesod.sheet.annotation.write.style.FreezePane;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

class SheetFreezePanePropertyTest {

@Test
void build_returnsNull_whenAnnotationIsNull() {
Assertions.assertNull(SheetFreezePaneProperty.build(null));
}

@Test
void build_mapsColSplitAndRowSplit() {
FreezePane annotation = FreezePaneClass.class.getAnnotation(FreezePane.class);
SheetFreezePaneProperty property = SheetFreezePaneProperty.build(annotation);

Assertions.assertNotNull(property);
Assertions.assertEquals(2, property.getColSplit());
Assertions.assertEquals(3, property.getRowSplit());
}

@Test
void build_usesDefaults_whenLeftmostColumnAndTopRowNotSet() {
FreezePane annotation = DefaultsClass.class.getAnnotation(FreezePane.class);
SheetFreezePaneProperty property = SheetFreezePaneProperty.build(annotation);

Assertions.assertNotNull(property);
Assertions.assertEquals(4, property.getLeftmostColumn());
Assertions.assertEquals(5, property.getTopRow());
}

@Test
void build_usesExplicitValues_whenLeftmostColumnAndTopRowSet() {
FreezePane annotation = ExplicitValuesClass.class.getAnnotation(FreezePane.class);
SheetFreezePaneProperty property = SheetFreezePaneProperty.build(annotation);

Assertions.assertNotNull(property);
Assertions.assertEquals(10, property.getLeftmostColumn());
Assertions.assertEquals(20, property.getTopRow());
}

@Test
void build_zeroColSplitAndRowSplit() {
FreezePane annotation = ZeroSplitClass.class.getAnnotation(FreezePane.class);
SheetFreezePaneProperty property = SheetFreezePaneProperty.build(annotation);

Assertions.assertNotNull(property);
Assertions.assertEquals(0, property.getColSplit());
Assertions.assertEquals(0, property.getRowSplit());
// When not specified, defaults should fall back to 0 (the split values)
Assertions.assertEquals(0, property.getLeftmostColumn());
Assertions.assertEquals(0, property.getTopRow());
}

@FreezePane(colSplit = 2, rowSplit = 3)
static class FreezePaneClass {}

@FreezePane(colSplit = 4, rowSplit = 5)
static class DefaultsClass {}

@FreezePane(colSplit = 1, rowSplit = 1, leftmostColumn = 10, topRow = 20)
static class ExplicitValuesClass {}

@FreezePane(colSplit = 0, rowSplit = 0)
static class ZeroSplitClass {}
}
Loading
Loading