최초 커밋

master
mjkhan21 8 months ago
commit 74a20dfd0c

@ -0,0 +1,182 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cokr.xit.base</groupId>
<artifactId>xit-docs</artifactId>
<version>23.04.01-SNAPSHOT</version>
<packaging>jar</packaging>
<name>xit-docs</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<spring.maven.artifact.version>5.3.20</spring.maven.artifact.version>
<org.egovframe.rte.version>4.1.0</org.egovframe.rte.version>
</properties>
<repositories>
<repository>
<id>mvn2s</id>
<url>https://repo1.maven.org/maven2/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>egovframe</id>
<url>https://maven.egovframe.go.kr/maven/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>maven-public</id>
<url>https://nas.xit.co.kr:8888/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>cokr.xit.base</groupId>
<artifactId>xit-foundation</artifactId>
<version>23.04.01-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<!-- 한컴 한글 라이브러리 -->
<dependency>
<groupId>kr.dogfoot</groupId>
<artifactId>hwplib</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>
<directory>${basedir}/target</directory>
<finalName>${project.artifactId}-${project.version}</finalName>
<resources>
<resource><directory>${basedir}/src/main/resources</directory></resource>
</resources>
<testResources>
<testResource><directory>${basedir}/src/test/resources</directory></testResource>
<testResource><directory>${basedir}/src/main/resources</directory></testResource>
</testResources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- EMMA -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>emma-maven-plugin</artifactId>
<version>1.0-alpha-3</version>
</plugin>
<!-- PMD manven plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<includes>
<include>**/*.class</include>
</includes>
</configuration>
</plugin>
<!-- EMMA -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<skipTests>true</skipTests>
<reportFormat>xml</reportFormat>
<excludes>
<exclude>**/Abstract*.java</exclude>
<exclude>**/*Suite.java</exclude>
</excludes>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>emma-maven-plugin</artifactId>
<inherited>true</inherited>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
</plugin>
</plugins>
</build>
<!-- Nexus deploy -->
<distributionManagement>
<snapshotRepository>
<id>maven-snapshot</id>
<url>https://nas.xit.co.kr:8888/repository/maven-snapshots/</url>
</snapshotRepository>
<repository>
<id>maven-release</id>
<url>https://nas.xit.co.kr:8888/repository/maven-releases/</url>
</repository>
</distributionManagement>
<!-- Nexus deploy -->
</project>

@ -0,0 +1,81 @@
package cokr.xit.base.docs.hwp;
import java.io.InputStream;
import java.util.List;
import org.springframework.core.io.ClassPathResource;
import cokr.xit.foundation.Assert;
import kr.dogfoot.hwplib.object.HWPFile;
import kr.dogfoot.hwplib.object.bodytext.control.Control;
import kr.dogfoot.hwplib.object.bodytext.control.ControlType;
import kr.dogfoot.hwplib.reader.HWPReader;
import kr.dogfoot.hwplib.tool.objectfinder.ControlFinder;
/**
* @author mjkhan
*/
public class HWP {
public static final String MIME_TYPE = "application/vnd.hancom.hwp";
/** .
* @param path
* @return
*/
public static HWPFile filepath(String path) {
try {
return HWPReader.fromFile(path);
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
/** .
* @param path
* @return
*/
public static HWPFile classpath(String path) {
try (InputStream input = new ClassPathResource(path).getInputStream()) {
return filestream(input);
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
/** InputStream .
* @param input InputStream
* @return
*/
public static HWPFile filestream(InputStream input) {
try {
return HWPReader.fromInputStream(input);
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
/**한글 파일*/
protected HWPFile file;
/** HWP .
* @param file
*/
public HWP(HWPFile file) {
this.file = file;
}
/** .
* @return
*/
public HWPFile getFile() {
return file;
}
/** .
* @param type
* @return
*/
public List<Control> getControls(ControlType type) {
return ControlFinder.find(file, (control, paragraph, section) -> type == control.getType());
}
}

@ -0,0 +1,179 @@
package cokr.xit.base.docs.hwp;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import cokr.xit.foundation.Assert;
import kr.dogfoot.hwplib.object.HWPFile;
import kr.dogfoot.hwplib.object.bodytext.control.Control;
import kr.dogfoot.hwplib.object.bodytext.control.ControlField;
import kr.dogfoot.hwplib.object.bodytext.paragraph.Paragraph;
import kr.dogfoot.hwplib.object.bodytext.paragraph.ParagraphList;
import kr.dogfoot.hwplib.object.bodytext.paragraph.text.ParaText;
import kr.dogfoot.hwplib.tool.objectfinder.FieldFinder;
import kr.dogfoot.hwplib.tool.objectfinder.TextBuffer;
import kr.dogfoot.hwplib.tool.objectfinder.forField.ForParagraphList;
/**
* @author mjkhan
*/
public class HWPWriter extends HWP {
private Image image;
private Table table;
private Header header;
/** HWPWriter .
* @param file
*/
public HWPWriter(HWPFile file) {
super(file);
}
/** / .
* @param name /
* @param objs
* @return HWPWriter
*/
public HWPWriter setValue(String name, Iterable<?> objs) {
try {
if (objs instanceof ArrayList) {
FieldFinder.setClickHereText(file, name, (ArrayList<String>)objs);
return this;
}
ArrayList<String> vals = new ArrayList<>();
for (Object val: objs) {
vals.add(val != null ? val.toString() : "");
}
FieldFinder.setClickHereText(file, name, vals);
return this;
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
/** / .
* @param name /
* @param vals
* @return HWPWriter
*/
public HWPWriter setValue(String name, Object... vals) {
return setValue(name, List.of(vals));
}
/** / .
* @param <T>
* @param t
* @param mappers / ,
* @return HWPWriter
*/
public <T> HWPWriter setValues(T t, Map<String, Function<T, Object>> mappers) {
if (!Assert.isEmpty(t)) {
mappers.forEach((k, mapper) -> setValue(k, mapper.apply(t)));
}
return this;
}
/** / .
* @param map
* @return HWPWriter
*/
public HWPWriter setValues(Map<?, ?> map) {
if (!Assert.isEmpty(map)) {
setValues(map, getMappers(map));
}
return this;
}
<T extends Map<?, ?>> Map<String, Function<T, Object>> getMappers(T map) {
return map.keySet().stream().collect(Collectors.toMap(
k -> k.toString(),
k -> m -> m.get(k)
));
}
ParaText getTextIn(Paragraph paragraph) {
ParaText paraText = paragraph.getText();
if (paraText == null) {
paragraph.createText();
paraText = paragraph.getText();
}
return paraText;
}
void setValue(Paragraph paragraph, Object val) throws Exception {
ParaText paraText = getTextIn(paragraph);
paraText.addString(val != null ? val.toString() : "");
}
<T extends Map<?, ?>> void setValues(ParagraphList paragraphs, T obj, Map<String, Function<T, Object>> mappers) throws Exception {
for (Paragraph paragraph: paragraphs) {
ArrayList<Control> controls = paragraph.getControlList();
Control control = !Assert.isEmpty(controls) ? controls.get(0) : null;
if (!(control instanceof ControlField)) continue;
ControlField controlField = (ControlField)control;
String fieldName = controlField.getName();
Function<T, Object> mapper = !Assert.isEmpty(fieldName) ? mappers.get(fieldName) : null;
if (mapper == null) continue;
Object val = mapper.apply(obj);
ArrayList<String> strs = new ArrayList<>();
strs.add(val != null ? val.toString() : "");
ForParagraphList.setFieldText(paragraphs, controlField.getType(), fieldName, new TextBuffer(strs));
}
}
/** Image .
* @return Image
*/
public Image image() {
return Assert.ifEmpty(image, () -> image = new Image(this));
}
/** Table .
* @param index
* @param rowstart
* @param rowspan
* @return Table
*/
public Table table(int index, int rowstart, int rowspan) {
return Assert.ifEmpty(table, () -> table = new Table(this)).of(index, rowstart, rowspan);
}
public Header header() {
return Assert.ifEmpty(header, () -> header = new Header(this));
}
/** OutputStream .
* @param out OutputStream
*/
public void write(OutputStream out) {
try {
kr.dogfoot.hwplib.writer.HWPWriter.toStream(file, out);
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
/** .
* @param filepath
* @return
*/
public File write(String filepath) {
File file = new File(filepath);
try (FileOutputStream out = new FileOutputStream(file)) {
write(out);
return file;
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
}

@ -0,0 +1,59 @@
package cokr.xit.base.docs.hwp;
import java.util.List;
import cokr.xit.foundation.Assert;
import kr.dogfoot.hwplib.object.bodytext.control.Control;
import kr.dogfoot.hwplib.object.bodytext.control.ControlHeader;
import kr.dogfoot.hwplib.object.bodytext.control.ControlType;
/** 릿
* @author mjkhan
*/
public class Header {
private HWPWriter writer;
Header(HWPWriter writer) {
this.writer = writer;
}
private List<Control> headers() {
return writer.getControls(ControlType.Header);
}
private ControlHeader header() {
List<Control> controls = writer.getControls(ControlType.Header);
if (controls.isEmpty())
throw new RuntimeException("ControlHeader not found");
return (ControlHeader)controls.get(0);
}
/** 릿 .
* @param index 릿
* @param obj
* @return Header HWPWriter
*/
public HWPWriter setValue(int index, Object obj) {
try {
List<Control> headers = headers();
if (headers.isEmpty())
throw new RuntimeException("ControlHeader not found");
ControlHeader header = (ControlHeader)headers.get(index);
writer.setValue(header.getParagraphList().getParagraph(0), obj);
return writer;
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
/**릿 .
* @param obj
* @return Header HWPWriter
*/
public HWPWriter setValue(Object obj) {
return setValue(0, obj);
}
}

@ -0,0 +1,240 @@
package cokr.xit.base.docs.hwp;
import java.awt.Rectangle;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.function.BiConsumer;
import cokr.xit.foundation.Assert;
import kr.dogfoot.hwplib.object.bindata.BinData;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.CtrlHeaderGso;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.gso.GsoHeaderProperty;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.gso.HeightCriterion;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.gso.HorzRelTo;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.gso.ObjectNumberSort;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.gso.RelativeArrange;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.gso.TextFlowMethod;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.gso.TextHorzArrange;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.gso.VertRelTo;
import kr.dogfoot.hwplib.object.bodytext.control.ctrlheader.gso.WidthCriterion;
import kr.dogfoot.hwplib.object.bodytext.control.gso.ControlRectangle;
import kr.dogfoot.hwplib.object.bodytext.control.gso.GsoControlType;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponent.ShapeComponentNormal;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponent.lineinfo.LineArrowShape;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponent.lineinfo.LineArrowSize;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponent.lineinfo.LineEndShape;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponent.lineinfo.LineInfo;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponent.lineinfo.LineType;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponent.lineinfo.OutlineStyle;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponent.shadowinfo.ShadowInfo;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponent.shadowinfo.ShadowType;
import kr.dogfoot.hwplib.object.bodytext.control.gso.shapecomponenteach.ShapeComponentRectangle;
import kr.dogfoot.hwplib.object.bodytext.paragraph.Paragraph;
import kr.dogfoot.hwplib.object.docinfo.bindata.BinDataCompress;
import kr.dogfoot.hwplib.object.docinfo.bindata.BinDataProperty;
import kr.dogfoot.hwplib.object.docinfo.bindata.BinDataState;
import kr.dogfoot.hwplib.object.docinfo.bindata.BinDataType;
import kr.dogfoot.hwplib.object.docinfo.borderfill.fillinfo.FillInfo;
import kr.dogfoot.hwplib.object.docinfo.borderfill.fillinfo.ImageFill;
import kr.dogfoot.hwplib.object.docinfo.borderfill.fillinfo.ImageFillType;
import kr.dogfoot.hwplib.object.docinfo.borderfill.fillinfo.PictureEffect;
/**
* @author mjkhan
*/
public class Image {
private HWPWriter writer;
private int instanceID = 0x5bb840e1;
Image(HWPWriter writer) {
this.writer = writer;
}
/** .
* @param path
* @param paragraph
* @param rect
* @return Image
*/
public Image add(String path, Paragraph paragraph, Rectangle rect) {
try {
int index = addData(path),
dataID = addToDocInfo(index, getExt(path));
ControlRectangle ctrlRect = newRect(paragraph);
setCtrlHeaderGso(ctrlRect, rect);
setShapeComponent(ctrlRect, rect, dataID);
setShapeComponentRectangle(ctrlRect, rect);
return this;
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
/** .
* @param path
* @param paragraph
* @return Image
*/
public Image add(String path, Paragraph paragraph) {
return add(path, paragraph, new Rectangle(50, 50, 100, 100));
}
/** .
* @param path
* @return
*/
public BiConsumer<Paragraph, Rectangle> add(String path) {
return !Assert.isEmpty(path) ? (paragraph, rect) -> add(path, paragraph, rect) : null;
}
private int addData(String path) throws Exception {
BinData binData = writer.file.getBinData();
int index = binData.getEmbeddedBinaryDataList().size() + 1;
String ext = getExt(path),
name = String.format("Bin%04X", index) + (!ext.isEmpty() ? "." + ext : ext);
try (FileInputStream input = new FileInputStream(path)) {
byte[] bytes = input.readAllBytes();
binData.addNewEmbeddedBinaryData(name, bytes, BinDataCompress.ByStorageDefault);
return index;
}
}
private static String getExt(String path) {
int pos = path.lastIndexOf(".");
return pos < 0 ? "" : path.substring(pos + 1);
}
private int addToDocInfo(int index, String ext) {
kr.dogfoot.hwplib.object.docinfo.BinData binData = new kr.dogfoot.hwplib.object.docinfo.BinData();
BinDataProperty property = binData.getProperty();
property.setType(BinDataType.Embedding);
property.setCompress(BinDataCompress.ByStorageDefault);
property.setState(BinDataState.NotAccess);
binData.setBinDataID(index);
binData.setExtensionForEmbedding(ext);
ArrayList<kr.dogfoot.hwplib.object.docinfo.BinData> dataList = writer.file.getDocInfo().getBinDataList();
dataList.add(binData);
return dataList.size();
}
private ControlRectangle newRect(Paragraph paragraph) {
writer.getTextIn(paragraph)
.addExtendCharForGSO();
return (ControlRectangle)paragraph.addNewGsoControl(GsoControlType.Rectangle);
}
private static int fromMM(int mm) {
return mm;
//return mm == 0 ? 1 : (int)((double)mm * 72000.0f / 254.0f + 0.5f);
}
private void setCtrlHeaderGso(ControlRectangle ctrlRect, Rectangle rect) {
CtrlHeaderGso header = ctrlRect.getHeader();
GsoHeaderProperty property = header.getProperty();
property.setLikeWord(false);
property.setApplyLineSpace(false);
property.setVertRelTo(VertRelTo.Para);
property.setVertRelativeArrange(RelativeArrange.TopOrLeft);
property.setHorzRelTo(HorzRelTo.Para);
property.setHorzRelativeArrange(RelativeArrange.TopOrLeft);
property.setVertRelToParaLimit(true);
property.setAllowOverlap(true);
property.setWidthCriterion(WidthCriterion.Absolute);
property.setHeightCriterion(HeightCriterion.Absolute);
property.setProtectSize(false);
property.setTextFlowMethod(TextFlowMethod.FitWithText);
property.setTextHorzArrange(TextHorzArrange.BothSides);
property.setObjectNumberSort(ObjectNumberSort.Figure);
header.setyOffset(fromMM(rect.y));
header.setxOffset(fromMM(rect.x));
header.setWidth(fromMM(rect.width));
header.setHeight(fromMM(rect.height));
header.setzOrder(0);
header.setOutterMarginLeft(0);
header.setOutterMarginRight(0);
header.setOutterMarginTop(0);
header.setOutterMarginBottom(0);
header.setInstanceId(instanceID);
header.setPreventPageDivide(false);
header.getExplanation().setBytes(null);
}
private void setShapeComponent(ControlRectangle ctrlRect, Rectangle rect, int dataID) {
ShapeComponentNormal shape = (ShapeComponentNormal) ctrlRect.getShapeComponent();
shape.setOffsetX(0);
shape.setOffsetY(0);
shape.setGroupingCount(0);
shape.setLocalFileVersion(1);
int width = fromMM(rect.width),
height = fromMM(rect.height);
shape.setWidthAtCreate(width);
shape.setHeightAtCreate(height);
shape.setWidthAtCurrent(width);
shape.setHeightAtCurrent(height);
shape.setRotateAngle(0);
shape.setRotateXCenter(fromMM(rect.width / 2));
shape.setRotateYCenter(fromMM(rect.height / 2));
shape.createLineInfo();
LineInfo line = shape.getLineInfo();
line.getProperty().setLineEndShape(LineEndShape.Flat);
line.getProperty().setStartArrowShape(LineArrowShape.None);
line.getProperty().setStartArrowSize(LineArrowSize.MiddleMiddle);
line.getProperty().setEndArrowShape(LineArrowShape.None);
line.getProperty().setEndArrowSize(LineArrowSize.MiddleMiddle);
line.getProperty().setFillStartArrow(true);
line.getProperty().setFillEndArrow(true);
line.getProperty().setLineType(LineType.None);
line.setOutlineStyle(OutlineStyle.Normal);
line.setThickness(0);
line.getColor().setValue(0);
shape.createFillInfo();
FillInfo fill = shape.getFillInfo();
fill.getType().setPatternFill(false);
fill.getType().setImageFill(true);
fill.getType().setGradientFill(false);
fill.createImageFill();
ImageFill imgFill = fill.getImageFill();
imgFill.setImageFillType(ImageFillType.FitSize);
imgFill.getPictureInfo().setBrightness((byte)0);
imgFill.getPictureInfo().setContrast((byte)0);
imgFill.getPictureInfo().setEffect(PictureEffect.RealPicture);
imgFill.getPictureInfo().setBinItemID(dataID);
shape.createShadowInfo();
ShadowInfo shadow = shape.getShadowInfo();
shadow.setType(ShadowType.None);
shadow.getColor().setValue(0xc4c4c4);
shadow.setOffsetX(283);
shadow.setOffsetY(283);
shadow.setTransparent((short)0);
shape.setMatrixsNormal();
}
private void setShapeComponentRectangle(ControlRectangle ctrlRect, Rectangle rect) {
ShapeComponentRectangle shapeRect = ctrlRect.getShapeComponentRectangle();
shapeRect.setRoundRate((byte)0);
shapeRect.setX1(0);
shapeRect.setY1(0);
int width = fromMM(rect.width),
height = fromMM(rect.height);
shapeRect.setX2(width);
shapeRect.setY2(0);
shapeRect.setX3(width);
shapeRect.setY3(height);
shapeRect.setX4(0);
shapeRect.setY4(height);
}
}

@ -0,0 +1,153 @@
package cokr.xit.base.docs.hwp;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import cokr.xit.foundation.Assert;
import kr.dogfoot.hwplib.object.bodytext.control.Control;
import kr.dogfoot.hwplib.object.bodytext.control.ControlField;
import kr.dogfoot.hwplib.object.bodytext.control.ControlTable;
import kr.dogfoot.hwplib.object.bodytext.control.ControlType;
import kr.dogfoot.hwplib.object.bodytext.control.table.Cell;
import kr.dogfoot.hwplib.object.bodytext.control.table.Row;
import kr.dogfoot.hwplib.object.bodytext.paragraph.Paragraph;
import kr.dogfoot.hwplib.object.bodytext.paragraph.ParagraphList;
import kr.dogfoot.hwplib.tool.objectfinder.TextBuffer;
import kr.dogfoot.hwplib.tool.objectfinder.forField.ForParagraphList;
/**
* @author mjkhan
*/
public class Table {
private int
index = -1,
start = -1,
rowspan = 1;
private HWPWriter writer;
Table(HWPWriter writer) {
this.writer = writer;
}
/** , .
* @param index
* @param start
* @param rowspan
* @return Table
*/
public Table of(int index, int start, int rowspan) {
this.index = index;
this.start = start;
this.rowspan = rowspan;
return this;
}
/** .
* @param <T>
* @param objs
* @param mappers . / .
* @return Image HWPWriter
*/
public <T> HWPWriter setValues(Iterable<T> objs, Map<String, Function<T, Object>> mappers) {
if (Assert.isEmpty(objs)) return writer;
Assert.notEmpty(mappers, "mappers");
ControlTable tableControl = Assert.notEmpty(getTable(index), "표 " + index);
ArrayList<Row>
rows = tableControl.getRowList(),
template = new ArrayList<>();
for (int i = start, length = start + rowspan; i < length; ++i)
template.add(rows.remove(start));
try {
for (T obj: objs) {
for (Row row: template) {
Row copy = row.clone();
for (Cell cell: copy.getCellList()) {
ParagraphList paragraphs = cell.getParagraphList();
String fieldName = cell.getListHeader().getFieldName();
Function<T, Object> mapper = !Assert.isEmpty(fieldName) ? mappers.get(fieldName) : null;
if (mapper != null) {
Object val = mapper.apply(obj);
Paragraph paragraph = paragraphs.getParagraph(0);
if (!(val instanceof BiConsumer)) {
writer.setValue(paragraph, val);
} else {
render(val, cell, paragraph);
}
} else {
for (Paragraph paragraph: paragraphs) {
ArrayList<Control> controls = paragraph.getControlList();
Control control = !Assert.isEmpty(controls) ? controls.get(0) : null;
if (!(control instanceof ControlField)) continue;
ControlField controlField = (ControlField)control;
fieldName = controlField.getName();
mapper = !Assert.isEmpty(fieldName) ? mappers.get(fieldName) : null;
if (mapper == null) continue;
Object val = mapper.apply(obj);
if (!(val instanceof BiConsumer)) {
ArrayList<String> strs = new ArrayList<>();
strs.add(val != null ? val.toString() : "");
ForParagraphList.setFieldText(paragraphs, controlField.getType(), fieldName, new TextBuffer(strs));
} else {
render(val, cell, paragraph);
}
}
}
}
rows.add(copy);
}
}
int rowCount = rows.size();
kr.dogfoot.hwplib.object.bodytext.control.table.Table table = tableControl.getTable();
table.setRowCount(rowCount);
ArrayList<Integer> cellCounts = table.getCellCountOfRowList();
cellCounts.clear();
for (int i = 0; i < rowCount; ++i) {
ArrayList<Cell> cells = rows.get(i).getCellList();
int cellCount = cells.size();
cellCounts.add(cellCount);
for (int j = 0; j < cellCount; ++j)
cells.get(j).getListHeader().setRowIndex(i);
}
return writer;
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
private void render(Object val, Cell cell, Paragraph paragraph) {
BiConsumer<Paragraph, Rectangle> renderer = (BiConsumer<Paragraph, Rectangle>)val;
int width = (int)cell.getListHeader().getWidth(),
height = (int)cell.getListHeader().getHeight();
renderer.accept(paragraph, new Rectangle(1, 1, width, height));
}
private ControlTable getTable(int index) {
List<Control> found = writer.getControls(ControlType.Table);
return !found.isEmpty() ? (ControlTable)found.get(index) : null;
}
/** .
* @param <T>
* @param dataset . / .
* @return Image HWPWriter
*/
public <T extends Map<?, ?>> HWPWriter setValues(Iterable<T> dataset) {
if (Assert.isEmpty(dataset)) return writer;
T map = dataset.iterator().next();
return setValues(dataset, writer.getMappers(map));
}
}

@ -0,0 +1,152 @@
package cokr.xit.base.docs.xls;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import com.fasterxml.jackson.core.type.TypeReference;
import cokr.xit.foundation.Assert;
/**
* <ul><li> </li>
* <li> () </li>
* <li></li>
* <li> </li>
* </ul>
* @author mjkhan
*/
public class CellDef {
/**CellDef .
* @param defs CellDef
* @param factory function
* @return
*/
public static List<Object> header(List<CellDef> defs, Supplier<Style> factory) {
ArrayList<Object> result = new ArrayList<>();
for (CellDef def: defs) {
result.add(def.label);
Style style = factory != null ? factory.get() : null;
if (style != null) {
style.width(def.width);
result.add(style);
}
}
return result;
}
/**valueMap CellDef .
* @param defs CellDef
* @param valueMap
*/
public static void setValues(List<CellDef> defs, Map<String, Object> valueMap) {
defs.forEach(def -> {
Object val = valueMap.getOrDefault(def.label, def.field);
def.value = Assert.notEmpty(val, "Value or style for " + def.label);
});
}
/**CellDef .
* @param defs CellDef
* @return
*/
public static Object[] values(List<CellDef> defs) {
if (defs == null)
return null;
ArrayList<Object> objs = new ArrayList<>();
for (CellDef def: defs) {
String field = def.getField();
Object val = def.getValue();
if (field != null) {
objs.add(field);
if (val != null)
objs.add(val);
} else {
objs.add(val);
}
}
return objs.toArray();
}
public static TypeReference<List<CellDef>> listType() {
return new TypeReference<List<CellDef>>() {};
}
private String
label,
field;
private int width;
private Object value;
/** .
* @return
*/
public String getLabel() {
return label;
}
/** .
* @param label
* @return CellDef
*/
public CellDef setLabel(String label) {
this.label = label;
return this;
}
/** .
* @return
*/
public String getField() {
return field;
}
/** .
* @param field
* @return CellDef
*/
public CellDef setField(String field) {
this.field = field;
return this;
}
/** .
* @return
* @return CellDef
*/
public int getWidth() {
return width;
}
/** .
* @param width
* @return CellDef
*/
public CellDef setWidth(int width) {
this.width = width;
return this;
}
/**, .
* @return ,
*/
public Object getValue() {
return value;
}
/**, .
* @param value ,
* @return CellDef
*/
public CellDef setValue(Object value) {
this.value = value;
return this;
}
}

@ -0,0 +1,88 @@
package cokr.xit.base.docs.xls;
import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.xssf.streaming.SXSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFVMLDrawing;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STTrueFalse;
import com.microsoft.schemas.vml.CTFill;
import com.microsoft.schemas.vml.CTShape;
import com.microsoft.schemas.vml.STFillType;
/**()
* @author mjkhan
*/
public class Comment {
private XLS xlsx;
private XSSFWorkbook workbook;
private CreationHelper factory;
private ClientAnchor anchor;
private XLS.Image image;
/** Comment .
* @param writer XLS
*/
public Comment(XLS writer) {
this.xlsx = writer;
workbook = this.xlsx.workbook.getXSSFWorkbook();
factory = workbook.getCreationHelper();
anchor = factory.createClientAnchor();
image = new XLS.Image(this.xlsx);
}
/** .
* @param str
* @return
*/
public XSSFComment create(String str) {
int row = xlsx.cell.getRowIndex();
anchor.setRow1(row);
anchor.setRow2(row + 17);
int col = xlsx.cell.getColumnIndex();
anchor.setCol1(col);
anchor.setCol2(col + 6);
SXSSFDrawing drawing = xlsx.worksheet.createDrawingPatriarch();
XSSFComment comment = (XSSFComment)drawing.createCellComment(anchor);
comment.setString(str);
xlsx.cell.setCellComment(comment);
return comment;
}
/** .
* @param title
* @param path
*/
public void setBackgroundImage(String title, String path) {
int picIndex = image.add(path);
XSSFPictureData pic = workbook.getAllPictures().get(picIndex);
XSSFVMLDrawing vml = xlsx.worksheet.getVMLDrawing(true);
RelationPart rp = vml.addRelation(null, XSSFRelation.IMAGES, pic);
int row = xlsx.cell.getRowIndex();
int col = xlsx.cell.getColumnIndex();
CTShape shape = vml.findCommentShape(row, col);
CTFill fill = shape.getFillArray(0);
fill.setColor2(fill.getColor());
fill.unsetColor();
fill.setRelid(rp.getRelationship().getId());
fill.setTitle(title);
fill.setRecolor(STTrueFalse.T);
fill.setRotate(STTrueFalse.T);
fill.setType(STFillType.FRAME);
}
/** .
* @param path
*/
public void setImageComment(String path) {
create("");
setBackgroundImage("", path);
}
}

@ -0,0 +1,206 @@
package cokr.xit.base.docs.xls;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import cokr.xit.foundation.data.Convert;
/**
* @author mjkhan
*/
public class Format implements Convert.Support {
private XLSWriter xlsx;
private Object key;
private UnaryOperator<Object> convert;
private CellStyle cellStyle;
private Consumer<Object> onCell;
/** Format .
* @param xlsx XLSWriter
*/
public Format(XLSWriter xlsx) {
this.xlsx = xlsx;
}
/** Format .
* @param key . Map
* @return Format
*/
public Format of(Object key) {
return new Format(xlsx).key(key);
}
/** .
* @param key . Map
* @return Format
*/
public Format key(Object key) {
this.key = key;
return this;
}
/** Format .
* Format .
* @return
* <ul><li> true</li>
* <li> false</li>
* </ul>
*/
public boolean hasValue() {
return convert != null || key != null;
}
/** Format .
* @param obj
* @return
*/
public Object value(Object obj) {
if (convert != null) {
return convert.apply(obj);
}
if (key != null && obj instanceof Map) {
Map<?, ?> map = (Map<?, ?>)obj;
return map.get(key);
}
throw new RuntimeException("Unable to get a value from " + obj);
}
/** .
* @param func
* @return Format
*/
public Format value(UnaryOperator<Object> func) {
convert = func;
return this;
}
/** .
* @param obj
* @return
* <ul><li> true</li>
* <li> false</li>
* </ul>
*/
static boolean hasValue(Object obj) {
if (obj instanceof CellStyle)
return false;
if (obj instanceof Style)
return false;
if (obj instanceof Format) {
Format format = (Format)obj;
return format.hasValue();
}
return true;
}
/** Map .
* @param obj
* @return
* <ul><li>Map </li>
* <li> null</li>
* </ul>
*/
static Object getKey(Object obj) {
if (obj instanceof CellStyle)
return null;
if (obj instanceof Style)
return null;
if (obj instanceof Format) {
Format format = (Format)obj;
if (format.key != null)
return format.key;
return null;
}
return obj;
}
/** CellStyle .
* @return CellStyle
*/
public CellStyle style() {
return cellStyle;
}
/** .
* @param obj Style CellStyle
* @return Format
*/
public Format style(Object obj) {
if (obj instanceof Style) {
cellStyle = cellStyle((Style)obj);
} else if (obj instanceof CellStyle) {
cellStyle = (CellStyle)obj;
} else
throw new IllegalArgumentException("Unable to get a CellStyle from " + obj);
return this;
}
/** Style CellStyle .
* @param style Style
* @return CellStyle
*/
public CellStyle cellStyle(Style style) {
return xlsx.cellStyle(style);
}
/** ( , ) .
* @return ( , )
*/
public CellStyle n_nn0() {
return cellStyle(new Style().alignment(HorizontalAlignment.RIGHT).dataFormat("#,##0"));
}
/** ( , , 2 ) .
* @return ( , , 2 )
*/
public CellStyle n_nn0_2() {
return cellStyle(Style.N_NN0_2);
}
/** (yyyy-MM-dd HH:mm:ss) .
* @return (yyyy-MM-dd HH:mm:ss)
*/
public CellStyle yyyy_mm_dd_hh_mm_ss() {
return cellStyle(Style.YYYY_MM_DD_HH_MM_SS);
}
/** (yyyy-MM-dd) .
* @return (yyyy-MM-dd)
*/
public CellStyle yyyy_mm_dd() {
return cellStyle(Style.YYYY_MM_DD);
}
/** (HH:mm:ss) .
* @return (HH:mm:ss)
*/
public CellStyle hh_mm_ss() {
return cellStyle(Style.HH_MM_SS);
}
/** .
* @param obj
* @return Format
*/
public Format onCell(Object obj) {
if (onCell != null)
onCell.accept(obj);
return this;
}
/** .
* @param func
* @return Format
*/
public Format onCell(Consumer<Object> func) {
onCell = func;
return this;
}
}

@ -0,0 +1,307 @@
package cokr.xit.base.docs.xls;
import java.util.function.Consumer;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/**
* @author mjkhan
*/
public class Style {
/** 빈 스타일 */
public static final Style NONE = new Style().seal();
/** 좌측 정렬 */
public static final Style LEFT = new Style().alignment(HorizontalAlignment.LEFT).seal();
/** 가운데 정렬 */
public static final Style CENTER = new Style().alignment(HorizontalAlignment.CENTER).seal();
/** 우측 정렬 */
public static final Style RIGHT = new Style().alignment(HorizontalAlignment.RIGHT).seal();
/**숫자 스타일(오른쪽 정렬, #,##0) */
public static final Style N_NN0 = new Style().dataFormat("#,##0").merge(RIGHT).seal();
/**숫자 스타일(오른쪽 정렬, #,###.00) */
public static final Style N_NN0_2 = new Style().dataFormat("#,###.00").merge(RIGHT).seal();
/**날짜시간 포맷(yyyy-MM-dd HH:mm:ss, 중앙 정렬) 스타일 */
public static final Style YYYY_MM_DD_HH_MM_SS = new Style().dataFormat("yyyy-MM-dd HH:mm:ss").merge(CENTER).seal();
/**날짜 포맷(yyyy-MM-dd, 중앙 정렬) 스타일 */
public static final Style YYYY_MM_DD = new Style().dataFormat("yyyy-MM-dd").merge(CENTER).seal();
/**시간 포맷(HH:mm:ss, 중앙 정렬) 스타일 */
public static final Style HH_MM_SS = new Style().dataFormat("HH:mm:ss").merge(Style.CENTER).seal();
private boolean sealed;
private Integer width;
private Short height;
private HorizontalAlignment horizontalAlignment;
private VerticalAlignment verticalAlignment;
private Border
borderTop,
borderRight,
borderBottom,
borderLeft;
private Short foregroundColor;
private Font font;
private String dataFormat;
/** .
* @param chars .
* @return Style
*/
public Style width(int chars) {
this.width = chars;
return this;
}
/** .
* @param height
* @return Style
*/
public Style height(short height) {
this.height = height;
return this;
}
/** .
* @param alignment
* @return Style
*/
public Style alignment(HorizontalAlignment alignment) {
ensureNotSealed();
horizontalAlignment = alignment;
return this;
}
/** .
* @param alignment
* @return Style
*/
public Style alignment(VerticalAlignment alignment) {
ensureNotSealed();
verticalAlignment = alignment;
return this;
}
/** .
* @param border
* @return Style
*/
public Style borderTop(Border border) {
ensureNotSealed();
borderTop = border;
return this;
}
/** .
* @param border
* @return Style
*/
public Style borderRight(Border border) {
ensureNotSealed();
borderRight = border;
return this;
}
/** .
* @param border
* @return Style
*/
public Style borderBottom(Border border) {
ensureNotSealed();
borderBottom = border;
return this;
}
/** .
* @param border
* @return Style
*/
public Style borderLeft(Border border) {
ensureNotSealed();
borderLeft = border;
return this;
}
/** .
* @param color
* @return Style
*/
public Style foregroundColor(short color) {
ensureNotSealed();
foregroundColor = color;
return this;
}
/** .
* @param font
* @return Style
*/
public Style font(Font font) {
ensureNotSealed();
this.font = font;
return this;
}
String dataFormat() {
return dataFormat;
}
/** .
* @param dataFormat
* @return Style
*/
public Style dataFormat(String dataFormat) {
ensureNotSealed();
this.dataFormat = dataFormat;
return this;
}
/** .
* @param style
*/
public void set(CellStyle style) {
if (style == null) return;
if (horizontalAlignment != null)
style.setAlignment(horizontalAlignment);
if (verticalAlignment != null)
style.setVerticalAlignment(verticalAlignment);
if (borderTop != null) {
if (borderTop.style != null)
style.setBorderTop(borderTop.style);
if (borderTop.color != null)
style.setTopBorderColor(borderTop.color);
}
if (borderRight != null) {
if (borderRight.style != null)
style.setBorderRight(borderRight.style);
if (borderRight.color != null)
style.setRightBorderColor(borderRight.color);
}
if (borderBottom != null) {
if (borderBottom.style != null)
style.setBorderBottom(borderBottom.style);
if (borderBottom.color != null)
style.setBottomBorderColor(borderBottom.color);
}
if (borderLeft != null) {
if (borderLeft.style != null)
style.setBorderLeft(borderLeft.style);
if (borderLeft.color != null)
style.setLeftBorderColor(borderLeft.color);
}
if (foregroundColor != null) {
style.setFillForegroundColor(foregroundColor);
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
}
if (font != null)
style.setFont(font);
}
/** .
* @param configurer
* @return Style
*/
public Style configure(Consumer<Style> configurer) {
ensureNotSealed();
if (configurer != null)
configurer.accept(this);
return this;
}
/** .
* @param other
* @return Style
*/
public Style merge(Style other) {
Style copy = new Style();
copy.width = this.width;
copy.height = this.height;
copy.horizontalAlignment = this.horizontalAlignment;
copy.verticalAlignment = this.verticalAlignment;
copy.borderTop = this.borderTop;
copy.borderRight = this.borderRight;
copy.borderBottom = this.borderBottom;
copy.borderLeft = this.borderLeft;
copy.foregroundColor = this.foregroundColor;
copy.font = this.font;
copy.dataFormat = this.dataFormat;
if (other.width != null)
copy.width = other.width;
if (other.height != null)
copy.height = other.height;
if (other.horizontalAlignment != null)
copy.horizontalAlignment = other.horizontalAlignment;
if (other.verticalAlignment != null)
copy.verticalAlignment = other.verticalAlignment;
if (other.borderTop != null)
copy.borderTop = other.borderTop;
if (other.borderRight != null)
copy.borderRight = other.borderRight;
if (other.borderBottom != null)
copy.borderBottom = other.borderBottom;
if (other.borderLeft != null)
copy.borderLeft = other.borderLeft;
if (other.foregroundColor != null)
copy.foregroundColor = other.foregroundColor;
if (other.font != null)
copy.font = other.font;
if (other.dataFormat != null)
copy.dataFormat = other.dataFormat;
return copy;
}
private Style seal() {
sealed = true;
return this;
}
private void ensureNotSealed() {
if (sealed)
throw new RuntimeException("The Style is sealed and unmodifieable");
}
/**
* @author mjkhan
*/
public static class Border {
private BorderStyle style;
private Short color;
/** .
* @param style
* @return
*/
public Border style(BorderStyle style) {
this.style = style;
return this;
}
/** .
* @param color
* @return
*/
public Border color(short color) {
this.color = color;
return this;
}
}
}

@ -0,0 +1,198 @@
package cokr.xit.base.docs.xls;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import cokr.xit.foundation.AbstractComponent;
/**
* @author mjkhan
*/
public abstract class XLS extends AbstractComponent {
/**엑셀 파일(*.xlsx)의 mime type */
public static final String MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
/**메모리에 적재하는 row의 갯수*/
protected int rowAccessWindowSize = 128;
/**워크북*/
protected SXSSFWorkbook workbook;
/**현재 처리 중인 워크시트*/
protected SXSSFSheet worksheet;
/**현재 처리 중인 row*/
protected SXSSFRow row;
/**현재 처리 중인 cell*/
protected SXSSFCell cell;
/** .
* @return
*/
public SXSSFWorkbook workbook() {
if (workbook != null)
return workbook;
try {
workbook = newWorkbook();
workbook.setCompressTempFiles(true);
return workbook;
} catch (Exception e) {
throw runtimeException(e);
}
}
/** .
* @return
* @throws Exception
*/
protected SXSSFWorkbook newWorkbook() throws Exception {
return new SXSSFWorkbook(rowAccessWindowSize);
}
/** .
* .
* @param index (0 )
* @return
*/
public XLS worksheet(int index) {
SXSSFSheet sheet = null;
try {
sheet = workbook().getSheetAt(index);
} catch (Exception e) {
sheet = workbook().createSheet();
sheet.setRandomAccessWindowSize(rowAccessWindowSize);
}
if (!sheet.equals(worksheet)) {
clear(false);
worksheet = sheet;
}
return this;
}
/** .
* .
* @param name
* @return
*/
public XLS worksheet(String name) {
SXSSFSheet sheet = null;
try {
SXSSFWorkbook wb = workbook();
sheet = wb.getSheet(name);
if (sheet == null) {
sheet = wb.createSheet(name);
sheet.setRandomAccessWindowSize(rowAccessWindowSize);
}
if (!sheet.equals(worksheet)) {
clear(false);
worksheet = sheet;
}
return this;
} catch (Exception e) {
throw runtimeException(e);
}
}
/** (row) .
* .
* @param index (0 )
* @return XLS
*/
public XLS row(int index) {
row = ifEmpty(worksheet.getRow(index), () -> worksheet.createRow(index));
return this;
}
/** (column) .
* .
* @param index (0 )
* @return XLS
*/
public XLS col(int index) {
cell = ifEmpty(row.getCell(index), () -> row.createCell(index));
return this;
}
/** .
* @param row
* @param col
* @return XLS
*/
public XLS cell(int row, int col) {
return row(row).col(col);
}
/** XLS row, cell, worksheet .
* @param all
* <ul><li> true</li>
* <li> false</li>
* </ul>
*/
protected void clear(boolean all) {
cell = null;
row = null;
worksheet = null;
if (all)
workbook = null;
rowAccessWindowSize = 128;
}
/**
* @author mjkhan
*/
public static class Image {
private XLS xlsx;
/** Image .
* @param xlsx XLS
*/
public Image(XLS xlsx) {
this.xlsx = xlsx;
}
/** .
* @param input InputStream
* @param picType {@link SXSSFWorkbook (SXSSFWorkbook.PICTURE_TYPE_XXX)}
* @return (1 )
*/
public int add(InputStream input, int picType) {
try {
return xlsx.workbook.addPicture(
input.readAllBytes(),
picType
);
} catch (Exception e) {
throw runtimeException(e);
}
}
/** .
* @param path
* @return (1 )
*/
public int add(String path) {
try (FileInputStream input = new FileInputStream(path)) {
return add(input, pictureType(path));
} catch (Exception e) {
throw runtimeException(e);
}
}
private int pictureType(String path) {
String str = path.toLowerCase();
return
str.endsWith(".png") ? SXSSFWorkbook.PICTURE_TYPE_PNG :
str.endsWith(".emf") ? SXSSFWorkbook.PICTURE_TYPE_EMF :
str.endsWith(".wmf") ? SXSSFWorkbook.PICTURE_TYPE_WMF :
str.endsWith(".pict") ? SXSSFWorkbook.PICTURE_TYPE_PICT :
str.endsWith(".dib") ? SXSSFWorkbook.PICTURE_TYPE_DIB :
SXSSFWorkbook.PICTURE_TYPE_JPEG;
}
}
}

@ -0,0 +1,311 @@
package cokr.xit.base.docs.xls;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.util.CellRangeAddress;
/**
* @author mjkhan
*/
public class XLSWriter extends XLS {
@Override
public XLSWriter worksheet(int index) {
super.worksheet(index);
return this;
}
@Override
public XLSWriter worksheet(String name) {
super.worksheet(name);
return this;
}
@Override
public XLSWriter row(int index) {
super.row(index);
return this;
}
@Override
public XLSWriter col(int index) {
super.col(index);
return this;
}
@Override
public XLSWriter cell(int row, int col) {
return row(row).col(col);
}
/** .
* @param firstRow
* @param lastRow
* @param firstCol
* @param lastCol
* @return XLSXWriter
*/
public XLSWriter merge(int firstRow, int lastRow, int firstCol, int lastCol) {
worksheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
return this;
}
/** .
* @param firstCol
* @param lastCol
* @return XLSXWriter
*/
public XLSWriter merge(int firstCol, int lastCol) {
int index = row.getRowNum();
return merge(index, index, firstCol, lastCol);
}
/** .
* @param objs
* @return XLSWriter
*/
public XLSWriter rowValues(Iterable<?> objs) {
return rowValues(objs, (Iterable<Object>)null);
}
private <T> XLSWriter rowValues(T t, Iterable<Object> objs) {
if (!isEmpty(t)) {
int c = cell.getColumnIndex();
if (isEmpty(objs)) {
if (t instanceof Map) {
Map<?, ?> map = (Map<?, ?>)t;
objs = map.keySet().stream().map(v -> (Object)v).toList();
} else if (t instanceof Iterable) {
objs = (Iterable<Object>)t;
} else {
objs = List.of(t);
}
}
for (Object obj: objs) {
boolean hasValue = Format.hasValue(obj);
if (hasValue)
col(c);
Object val = null;
Format format = null;
if (obj instanceof Format)
format = (Format)obj;
if (format != null)
val = format.value(t);
else {
Object key = Format.getKey(obj);
if (key != null && t instanceof Map)
val = ((Map<?, ?>)t).get(key);
else
val = obj;
}
setCellValue(val);
setCellStyle(obj);
if (format != null)
format.onCell(t);
if (hasValue)
++c;
}
}
return this;
}
/** .
* .<br />
* {@link Format} .<br />
* .
* <pre><code> List&lt;MyObject> dataset = ...;
* XLSWriter xlsx = new XLSWriter()
* .worksheet(0) // 워크시트 지정
* .cell(0, 0) // 작업셀 지정
* .values(
* dataset,
* myObj -> List.of(
* myObj.getPropA(),
* myObj.getPropB(),
* myObj.getPropC()
* )
* );</code></pre>
* PropB, PropC .
* <pre><code> Format format = new Format(xlsx);
* CellStyle numeric = format.n_nn0();
* CellStyle datetime = format.yyyy_mm_dd_hh_mm_ss();
* ...
* xlsx.values(
* dataset,
* myObj -> List.of(
* myObj.getPropA(),
* myObj.getPropB(),
* numeric,
* myObj.getPropC(),
* datetime
* )
* );</code></pre>
* @param dataset
* @param mapper , Style, CellStyle
* @return XLSXWriter
*/
public <T extends Iterable<?>> XLSWriter values(Iterable<T> dataset, Function<T, Iterable<Object>> mapper) {
if (!isEmpty(dataset)) {
int r = cell.getRowIndex(),
c = cell.getColumnIndex();
for (T rec: dataset) {
cell(r, c);
Iterable<Object> vals = mapper != null ? mapper.apply(rec) : (Iterable<Object>)rec;
rowValues(rec, vals);
++r;
}
}
return this;
}
/** .
* .<br />
* {@link Format} .<br />
* .
* <pre><code> List&lt;DataObject> dataset = ...;
* XLSWriter xlsx = new XLSWriter()
* .worksheet(0) // 워크시트 지정
* .cell(0, 0) // 작업셀 지정
* .values(dataset);</code></pre>
* .
* <pre><code> xlsx.values(dataset, "PAYER", "RCPT_AMT", "RCPT_DT");</code></pre>
* RCPT_AMT, RCPT_DT .
* <pre><code> Format format = new Format(xlsx);
* CellStyle numeric = format.n_nn0();
* CellStyle datetime = format.yyyy_mm_dd_hh_mm_ss();
* ...
* xlsx.values(dataset, "PAYER", "RCPT_AMT", numeric, "RCPT_DT", datetime));</code></pre>
* @param dataset
* @param objs , CellStyle, {@link Style}, {@link Format}
* @return XLSXWriter
*/
public <T extends Map<?, ?>> XLSWriter values(Iterable<T> dataset, Object... objs) {
if (!isEmpty(dataset)) {
int r = cell.getRowIndex(),
c = cell.getColumnIndex();
List<Object> list = !isEmpty(objs) ? List.of(objs) : Collections.emptyList();
for (T row: dataset) {
cell(r, c);
rowValues(row, list);
++r;
}
}
return this;
}
/** Map .
* .<br />
* {@link Format} .<br />
* .
* <pre><code> DataObject row = ...;
* XLSWriter xlsx = new XLSWriter()
* .worksheet(0) // 워크시트 지정
* .cell(0, 0) // 작업셀 지정
* .rowValues(row);</code></pre>
* .
* <pre><code> xlsx.rowValues(row, "PAYER", "RCPT_AMT", "RCPT_DT");</code></pre>
* RCPT_AMT, RCPT_DT .
* <pre><code> Format format = new Format(xlsx);
* CellStyle numeric = format.n_nn0();
* CellStyle datetime = format.yyyy_mm_dd_hh_mm_ss();
* ...
* xlsx.rowValues(row, "PAYER", "RCPT_AMT", numeric, "RCPT_DT", datetime));</code></pre>
* @param map
* @param objs , CellStyle, {@link Style}, {@link Format}
* @return XLSWriter
*/
public XLSWriter rowValues(Map<?, ?> map, Object... objs) {
return rowValues(map, !isEmpty(objs) ? List.of(objs) : Collections.emptyList());
}
/** .
* @param obj
* @return XLSXWriter
*/
public XLSWriter value(Object obj) {
if (obj != null) {
setCellValue(obj);
setCellStyle(obj);
}
return this;
}
void setCellValue(Object val) {
if (val instanceof String) {
cell.setCellValue((String)val);
} else if (val instanceof Number) {
Number number = (Number)val;
cell.setCellValue(number.doubleValue());
} else if (val instanceof Date) {
cell.setCellValue((Date)val);
} else if (val instanceof Boolean) {
Boolean b = (Boolean)val;
cell.setCellValue(b.booleanValue());
}
}
CellStyle cellStyle(Style style) {
CellStyle cellStyle = workbook.createCellStyle();
style.set(cellStyle);
if (style.dataFormat() != null) {
cellStyle.setDataFormat(workbook.createDataFormat().getFormat(style.dataFormat()));
}
return cellStyle;
}
void setCellStyle(Object obj) {
CellStyle cellStyle = null;
if (obj instanceof Format)
cellStyle = ((Format)obj).style();
else if (obj instanceof Style)
cellStyle = cellStyle((Style)obj);
else if (obj instanceof CellStyle)
cellStyle = (CellStyle)obj;
if (cellStyle != null)
cell.setCellStyle(cellStyle);
}
/** OutputStream .
* @param out OutputStream
*/
public void write(OutputStream out) {
try {
workbook.write(out);
workbook.dispose();
} catch (Exception e) {
throw runtimeException(e);
} finally {
clear(true);
}
}
/** .
* @param filepath
* @return
*/
public File write(String filepath) {
File file = new File(filepath);
try (FileOutputStream out = new FileOutputStream(file)) {
write(out);
return file;
} catch (Exception e) {
throw runtimeException(e);
}
}
}

@ -0,0 +1,142 @@
package cokr.xit.base.docs.hwp;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import org.junit.jupiter.api.Test;
import cokr.xit.foundation.Assert;
import cokr.xit.foundation.data.DataFormat;
import cokr.xit.foundation.data.DataObject;
import kr.dogfoot.hwplib.object.HWPFile;
public class HWPTest {
private String path(String str, boolean delete) {
String path = "src\\test\\resources\\" + str;
File file = new File(path);
if (delete && file.exists())
file.delete();
return path;
}
@Test
void setValue() {
HWPFile file = HWPWriter.filepath(path("files\\hwp-test.hwp", false));
HWPWriter writer = new HWPWriter(file);
/*
TestObject tobj = new TestObject()
.setName("홍길동")
.setResidentNo("123456780123")
.setAddress("서울특별시 양천구")
.setTotalCount(23)
.setTotalAmt(230000000);
writer.setValues(
tobj,
Map.of(
"성명", TestObject::getName,
"주민번호", TestObject::getResidentNo,
"주소", TestObject::getAddress,
"총건수", TestObject::getTotalCount,
"총금액", TestObject::getTotalAmt
)
);
*/
writer
.setValues(Map.of(
"사용자", "이몽룡",
"출력일자", DataFormat.yyyy_mm_dd("20240312"),
"성명", "홍길동",
"주민번호", "1234567890123",
"주소", "서울특별시 양천구",
"총건수", 23,
"총금액", DataFormat.n_nn0(230000000)
));
List<DataObject> list = IntStream.range(0, 20).boxed().map(i ->
(DataObject)new DataObject()
.set("과태료", "과태료 " + i)
.set("단속일시", "단속일시 " + i)
.set("차량번호", "123가456" + (i % 10))
.set("고지번호", "고지번호 " + i)
.set("금액", "금액 " + i)
.set("가상계좌번호", "가상계좌번호 " + i)
.set("처리상태", "처리상태 " + i)
.set("처리일자", "처리일자 " + i)
.set("시군구명", "시군구명 " + i)
.set("단속장소", "단속장소 " + i)
.set("대체차량번호", "234나567" + (i % 10))
.set("전자납부번호", "전자납부번호 " + i)
.set("납부기한", "납부기한 " + i)
.set("수납일자", "수납일자 " + i)
.set("단속사진", writer.image().add(path("files\\" + (i % 2 == 0 ? "4148020220006850A.jpg" : "4148020220006869A.jpg"), false)))
).toList();
writer.table(2, 3, 4).setValues(list);
//writer.header().setValue("abc");
try (FileOutputStream out = new FileOutputStream(path("files\\hwp-test-result.hwp", true))) {
writer.write(out);
} catch (Exception e) {
throw Assert.runtimeException(e);
}
}
static class TestObject {
private String
name,
residentNo,
address;
private int totalCount;
private long totalAmt;
public String getName() {
return name;
}
public TestObject setName(String name) {
this.name = name;
return this;
}
public String getResidentNo() {
return residentNo;
}
public TestObject setResidentNo(String residentNo) {
this.residentNo = residentNo;
return this;
}
public String getAddress() {
return address;
}
public TestObject setAddress(String address) {
this.address = address;
return this;
}
public int getTotalCount() {
return totalCount;
}
public TestObject setTotalCount(int totalCount) {
this.totalCount = totalCount;
return this;
}
public long getTotalAmt() {
return totalAmt;
}
public TestObject setTotalAmt(long totalAmt) {
this.totalAmt = totalAmt;
return this;
}
}
}

@ -0,0 +1,203 @@
package cokr.xit.base.docs.xls;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.jupiter.api.Test;
import cokr.xit.foundation.data.DataObject;
public class XLSTest {
private String file(String str) {
String path = "C:\\project\\base project\\xit-docs\\src\\test\\resources\\" + str;
File file = new File(path);
if (file.exists())
file.delete();
return path;
}
@Test
void sxssf() {
XLSWriter xlsx = new XLSWriter().worksheet("테스트 시트");
Format format = new Format(xlsx);
CellStyle
datetime = format.yyyy_mm_dd_hh_mm_ss(),
numeric = format.n_nn0(),
blue = format.cellStyle(new Style().foregroundColor(IndexedColors.LIGHT_BLUE.getIndex()));
xlsx.row(0)
.col(0).value("테스트0")
.col(1).value("테스트1")
.col(2).value(new Date()).value(datetime)
.col(3).value(1000000.0101).value(numeric)
.cell(2, 0)
.rowValues(List.of("테스트 1", blue, "테스트 2", 2500000, numeric));
List<DataObject> dataset = List.of(
new DataObject().set("field0", "값 0, 0").set("field1", "값 0, 1").set("field2", 10000),
new DataObject().set("field0", "값 1, 0").set("field1", "값 1, 1").set("field2", 20000),
new DataObject().set("field0", "값 2, 0").set("field1", "값 2, 1").set("field2", 30000),
new DataObject().set("field0", "값 3, 0").set("field1", "값 3, 1").set("field2", 40000),
new DataObject().set("field0", "값 4, 0").set("field1", "값 4, 1").set("field2", 50000)
);
xlsx.cell(4, 0)
.values(
dataset,
"field0", "field1",
"field2", numeric,
format.of(null).value(obj -> format.toInt(((Map)obj).get("field2")) * 2).style(numeric)
)
// .values(dataset)
.write(file("sxssf.xlsx"));
}
@Test
void sxssf2() {
Date now = new Date();
List<DataObject> dataset = List.of(
new DataObject().set("no", 1).set("title", "제목 1").set("content", "내용 1").set("amt", 1000000).set("regDate", now),
new DataObject().set("no", 2).set("title", "제목 2").set("content", "내용 2").set("amt", 2000000).set("regDate", now),
new DataObject().set("no", 3).set("title", "제목 3").set("content", "내용 3").set("amt", 3000000).set("regDate", now),
new DataObject().set("no", 4).set("title", "제목 4").set("content", "내용 4").set("amt", 4000000).set("regDate", now),
new DataObject().set("no", 5).set("title", "제목 5").set("content", "내용 5").set("amt", 5000000).set("regDate", now)
);
XLSWriter xlsx = new XLSWriter().worksheet(0);
Format format = new Format(xlsx);
CellStyle
datetime = format.yyyy_mm_dd_hh_mm_ss(),
numeric = format.n_nn0();
xlsx.cell(5, 0)
//.values(dataset, "no", "title", "content", "amt", numeric, "regDate", datetime);
.values(dataset, "no", "title", "content",
"amt", numeric,
format.of(null).value(obj -> ((Map)obj).get("amt") + " 원"),
"regDate", datetime
)
.write(file("sxssf2.xlsx"));
}
@Test
void sxssf3() {
Date now = new Date();
List<DataObject> dataset = List.of(
new DataObject().set("no", 1).set("title", "제목 1").set("content", "내용 1").set("amt", 1000000).set("regDate", now),
new DataObject().set("no", 2).set("title", "제목 2").set("content", "내용 2").set("amt", 2000000).set("regDate", now),
new DataObject().set("no", 3).set("title", "제목 3").set("content", "내용 3").set("amt", 3000000).set("regDate", now),
new DataObject().set("no", 4).set("title", "제목 4").set("content", "내용 4").set("amt", 4000000).set("regDate", now),
new DataObject().set("no", 5).set("title", "제목 5").set("content", "내용 5").set("amt", 5000000).set("regDate", now)
);
XLSWriter xlsx = new XLSWriter().worksheet(0);
Format format = new Format(xlsx);
CellStyle
datetime = format.yyyy_mm_dd_hh_mm_ss(),
numeric = format.n_nn0();
List<CellDef> cellDefs = List.of(
new CellDef().setLabel("번호").setField("no"),
new CellDef().setLabel("제목").setField("title"),
new CellDef().setLabel("내용").setField("content"),
// new CellDef().setLabel("금액").setField("amt").setValue(format.of("amt").style(numeric)),
new CellDef().setLabel("금액").setField("amt").setValue(numeric),
// new CellDef().setLabel("등록일시").setField("regDate").setValue(format.of("regDate").style(datetime))
new CellDef().setLabel("금액 2").setValue(format.of(null).value(obj -> ((Map)obj).get("amt") + " 원")),
new CellDef().setLabel("등록일시").setField("regDate").setValue(datetime)
);
xlsx.cell(4, 0)
.rowValues(CellDef.header(cellDefs, null))
.cell(5, 0)
.values(dataset, CellDef.values(cellDefs))
.write(file("sxssf3.xlsx"));
}
@Test
void pictureComment() {
Date now = new Date();
String dir = "C:\\project\\base project\\xit-docs\\src\\test\\resources\\files\\",
path1 = dir + "4148020220006850A.jpg",
path2 = dir + "4148020220006869A.jpg";
List<DataObject> dataset = List.of(
new DataObject().set("no", 1).set("title", "제목 1").set("content", "내용 1").set("pic", path1).set("amt", 1000000).set("regDate", now),
new DataObject().set("no", 2).set("title", "제목 2").set("content", "내용 2").set("pic", path2).set("amt", 2000000).set("regDate", now)
);
XLSWriter xlsx = new XLSWriter()
.worksheet(0)
.cell(3, 0);
Format format = new Format(xlsx);
CellStyle
datetime = format.yyyy_mm_dd_hh_mm_ss(),
currency = format.cellStyle(new Style().dataFormat("#,##0 원").merge(Style.RIGHT));
Comment comment = new Comment(xlsx);
xlsx.values(
dataset, "no", "title", "content",
format.of(null)
.value(row -> null)
.onCell(row -> comment.setImageComment((String)((Map)row).get("pic"))),
"amt", currency,
format.of("regDate").style(datetime)
)
.write(file("picture-comment.xlsx"));
}
@Test
void twoSheets() {
Date now = new Date();
List<DataObject> dataset = List.of(
new DataObject().set("no", 1).set("title", "제목 1").set("content", "내용 1").set("amt", 1000000).set("regDate", now),
new DataObject().set("no", 2).set("title", "제목 2").set("content", "내용 2").set("amt", 2000000).set("regDate", now),
new DataObject().set("no", 3).set("title", "제목 3").set("content", "내용 3").set("amt", 3000000).set("regDate", now),
new DataObject().set("no", 4).set("title", "제목 4").set("content", "내용 4").set("amt", 4000000).set("regDate", now),
new DataObject().set("no", 5).set("title", "제목 5").set("content", "내용 5").set("amt", 5000000).set("regDate", now)
);
XLSWriter xlsx = new XLSWriter().worksheet("첫번째 시트");
Format format = new Format(xlsx);
CellStyle
datetime = format.yyyy_mm_dd_hh_mm_ss(),
numeric = format.n_nn0();
List<CellDef> cellDefs = List.of(
new CellDef().setLabel("번호").setField("no"),
new CellDef().setLabel("제목").setField("title"),
new CellDef().setLabel("내용").setField("content"),
new CellDef().setLabel("금액").setField("amt").setValue(numeric),
new CellDef().setLabel("금액 2").setValue(format.of(null).value(obj -> ((Map)obj).get("amt") + " 원")),
new CellDef().setLabel("등록일시").setField("regDate").setValue(datetime)
);
xlsx.cell(5, 0)
.values(dataset, CellDef.values(cellDefs));
String dir = "C:\\project\\base project\\xit-docs\\src\\test\\resources\\files\\",
path1 = dir + "4148020220006850A.jpg",
path2 = dir + "4148020220006869A.jpg";
dataset = List.of(
new DataObject().set("no", 1).set("title", "제목 1").set("content", "내용 1").set("pic", path1).set("amt", 1000000).set("regDate", now),
new DataObject().set("no", 2).set("title", "제목 2").set("content", "내용 2").set("pic", path2).set("amt", 2000000).set("regDate", now)
);
xlsx.worksheet("두번째 시트").cell(3, 0);
CellStyle currency = format.cellStyle(new Style().dataFormat("#,##0 원").merge(Style.RIGHT));
Comment comment = new Comment(xlsx);
xlsx.values(
dataset, "no", "title", "content",
format.of(null)
.value(row -> null)
.onCell(row -> comment.setImageComment((String)((Map)row).get("pic"))),
"amt", currency,
format.of("regDate").style(datetime)
)
.write(file("two-sheets.xlsx"));
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save