From db76cf75dc9853a191e0bf94669f2ec1043e0332 Mon Sep 17 00:00:00 2001 From: Xujian66 <91264074+Xujian66@users.noreply.github.com> Date: Sun, 11 Oct 2026 02:51:06 +0800 Subject: [PATCH] Escape custom property names in workbook metadata --- .../java/org/dhatim/fastexcel/Properties.java | 8 +-- .../org/dhatim/fastexcel/PropertiesTest.java | 70 +++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 fastexcel-writer/src/test/java/org/dhatim/fastexcel/PropertiesTest.java diff --git a/fastexcel-writer/src/main/java/org/dhatim/fastexcel/Properties.java b/fastexcel-writer/src/main/java/org/dhatim/fastexcel/Properties.java index 281ca448..a56f0c7d 100644 --- a/fastexcel-writer/src/main/java/org/dhatim/fastexcel/Properties.java +++ b/fastexcel-writer/src/main/java/org/dhatim/fastexcel/Properties.java @@ -158,7 +158,7 @@ public TextProperty(String key, String value) { @Override public void write(Writer w, int pid) throws IOException { - w.append(""); + w.append(""); w.appendEscaped(value); w.append(""); } @@ -171,7 +171,7 @@ public DateProperty(String key, Instant value) { @Override public void write(Writer w, int pid) throws IOException { - w.append("" + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX").withZone(ZoneId.of("UTC")).format(value) + ""); + w.append("" + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX").withZone(ZoneId.of("UTC")).format(value) + ""); } } @@ -182,7 +182,7 @@ public NumberProperty(String key, BigDecimal value) { @Override public void write(Writer w, int pid) throws IOException { - w.append("" + value.toPlainString() + ""); + w.append("" + value.toPlainString() + ""); } } @@ -193,7 +193,7 @@ public BoolProperty(String key, Boolean value) { @Override public void write(Writer w, int pid) throws IOException { - w.append("" + value.toString() + ""); + w.append("" + value.toString() + ""); } } diff --git a/fastexcel-writer/src/test/java/org/dhatim/fastexcel/PropertiesTest.java b/fastexcel-writer/src/test/java/org/dhatim/fastexcel/PropertiesTest.java new file mode 100644 index 00000000..e54958ee --- /dev/null +++ b/fastexcel-writer/src/test/java/org/dhatim/fastexcel/PropertiesTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2016 Dhatim. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dhatim.fastexcel; + +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.jupiter.api.Test; +import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty; + +import java.io.ByteArrayInputStream; +import java.math.BigDecimal; +import java.time.Instant; +import java.util.function.Consumer; + +import static org.assertj.core.api.Assertions.assertThat; + +class PropertiesTest { + private static final String PROPERTY_NAME = "A & \"B\" 'D' <"; + + @Test + void textPropertyNameIsEscaped() throws Exception { + assertPropertyRoundTrip(properties -> properties.setTextProperty(PROPERTY_NAME, "Text & value"), + property -> assertThat(property.getLpwstr()).isEqualTo("Text & value")); + } + + @Test + void datePropertyNameIsEscaped() throws Exception { + Instant value = Instant.parse("2026-01-02T03:04:05Z"); + assertPropertyRoundTrip(properties -> properties.setDateProperty(PROPERTY_NAME, value), + property -> assertThat(property.getFiletime().toInstant()).isEqualTo(value)); + } + + @Test + void numberPropertyNameIsEscaped() throws Exception { + assertPropertyRoundTrip(properties -> properties.setNumberProperty(PROPERTY_NAME, new BigDecimal("123.5")), + property -> assertThat(property.getR8()).isEqualTo(123.5)); + } + + @Test + void boolPropertyNameIsEscaped() throws Exception { + assertPropertyRoundTrip(properties -> properties.setBoolProperty(PROPERTY_NAME, true), + property -> assertThat(property.getBool()).isTrue()); + } + + private void assertPropertyRoundTrip(Consumer configure, Consumer assertValue) + throws Exception { + byte[] bytes = CorrectnessTest.writeWorkbook(workbook -> { + workbook.newWorksheet("Sheet1"); + configure.accept(workbook.properties()); + }); + try (XSSFWorkbook workbook = new XSSFWorkbook(new ByteArrayInputStream(bytes))) { + CTProperty property = workbook.getProperties().getCustomProperties().getProperty(PROPERTY_NAME); + assertThat(property).isNotNull(); + assertThat(property.getName()).isEqualTo(PROPERTY_NAME); + assertValue.accept(property); + } + } +}