Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: Add support for custom parsing placeholder syntax for template filling#398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
Hui-FatGod wants to merge2 commits intoapache:main
base:main
Choose a base branch
Loading
fromHui-FatGod:main

Conversation

Hui-FatGod
Copy link

Background

​Fastexcel is a very excellent excel operation tool java library. One of the advanced features included, template filling, is also stable and trustworthy. However, in the actual application of some migration scenarios, the template filling function of fastexcel may appear inadequate. This limitation is mainly due to the fixed template placeholder rules of fastexcel, which cannot adapt to the template placeholder syntax when migrating from other libraries (which may be some good commercial libraries like Aspose, or internal enterprise/organization framework libraries, etc.). I think this flaw can be fatal, especially in the migration scenario I just described. For example, the underlying Excel operation of a large business system is migrated from Aspose to Fastexcel. The original system contains a large number of (the order of magnitude may reach thousands, even tens of thousands) of original templates. At this time, it is obviously unrealistic to change the placeholder syntax of all the templates, and the cost is too high.

Implementation

​To address the aforementioned issues, I made some modifications to the fill in the write package. My approach was to keep changes to the original code logic minimal. Specifically, I introduced an abstraction layer between the template cell string value andAnalysisCell, represented asCollection<TemplateStringPart>.

​In this implementation, simple string values are first parsed into mutil parts(currently categorized into three types: plain text type, normal variable type, and collection variable type). This parsing behavior can be customized by fastexcel users. The interface for this functionality is namedTemplateStringParseHandler. Additionally, I encapsulated fastexcel's original parsing logic within aDefaultTemplateStringParseHandler.

notes

​Other than that, I've made a slight logical change to the'{}' placeholder syntax parsing. I made this change as the second commit in this PR, mainly to solve the original fastexcel parsing'{}' placeholder syntax,'{foo\}' or'}foo{' this situation will throw an index out of bounds exception, even though this syntax will not appear in the actual application, but I still think it should be considered.

questions

  1. When the member methodreadTemplateData inExcelWriteFillExecutor is called, theprepareData method is invoked to obtain the prepared datapreparedData (string). And thepreparedData will be filled into the cell first. But it seems that this' preparedData 'does not contain the last string of theAnalysisCell. What is the specific reason for this? To adapt to this phenomenon, when preparing this data, I also discarded the last textTemplateStringPart (multiple text parts will be merged).
  2. As stated above, I will parse the behavior of the template string syntax abstractedTemplateStringParseHandler interface. My initial plan was to place this custom setting entry in the parameters of thewithTemplate method ofExcelWriteBuilder. However, eventually, following the principle of minimal modification, I set it in theFillConfig configuration. When comparing these two schemes, I think both are acceptable. After all, in the vast majority of cases, a template will definitely have only one grammar. If there is a better solution, please ignore this question.

Copy link
Contributor

@CopilotCopilotAI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Pull Request Overview

This PR adds a flexible placeholder parsing layer to the existing template fill feature, allowing users to provide custom parsing rules without altering core logic.

  • IntroducesTemplateStringPart abstraction and aTemplateStringParseHandler interface.
  • AddsFillConfig.templateStringParseHandler with a default implementation.
  • RefactorsExcelWriteFillExecutor to delegate placeholder parsing and rebuilds the core fill loop around parsed parts.

Reviewed Changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
FillTest.javaAddedunconventionalFill example test demonstrating custom placeholders.
TemplateStringPart.javaNew immutable value type representing segments of a template string.
FillConfig.javaExposedtemplateStringParseHandler in configuration and set default ininit().
DefaultTemplateStringParseHandler.javaProvided default parsing logic for{} and escaped braces.
TemplateStringParseHandler.javaDefined interface for pluggable parsing strategy.
ExcelWriteFillExecutor.javaRemoved inline parsing, wired in handler, and rebuilt fill logic aroundTemplateStringPart.
TemplateStringPartType.javaEnum for part kinds: TEXT, COMMON_VARIABLE, COLLECTION_VARIABLE.
Comments suppressed due to low confidence (3)

fastexcel-test/src/test/java/cn/idev/excel/test/demo/fill/FillTest.java:274

  • TheunconventionalFill test writes output but does not verify any cell values or file contents. Consider adding assertions that read back the generated sheets and confirm that placeholders were replaced correctly.
            excelWriter.fill(getListMap.apply(10), EasyExcel.writerSheet("list").build());

fastexcel-core/src/main/java/cn/idev/excel/write/executor/ExcelWriteFillExecutor.java:495

  • Missing import forCollectionUtils, which will cause a compilation error. Please add the appropriate import (e.g.,import cn.idev.excel.util.CollectionUtils;).
        if (CollectionUtils.isEmpty(templateStringParts)) {

fastexcel-core/src/main/java/cn/idev/excel/write/executor/ExcelWriteFillExecutor.java:117

  • IffillConfig.init() has not been called beforefill,templateStringParseHandler may be null. Ensureinit() is invoked on theFillConfig instance prior to retrieving the handler.
        currentTemplateStringParseHandler = fillConfig.getTemplateStringParseHandler();

Comment on lines 106 to 107
stringValue = stringValue.replaceAll(ESCAPE_FILL_PREFIX, FILL_PREFIX);
stringValue = stringValue.replaceAll(ESCAPE_FILL_SUFFIX, FILL_SUFFIX);
Copy link

CopilotAIJul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

[nitpick] UsingreplaceAll compiles the regex every call; consider usingString.replace for literal replacements to improve performance.

Suggested change
stringValue =stringValue.replaceAll(ESCAPE_FILL_PREFIX,FILL_PREFIX);
stringValue =stringValue.replaceAll(ESCAPE_FILL_SUFFIX,FILL_SUFFIX);
stringValue =stringValue.replace(ESCAPE_FILL_PREFIX,FILL_PREFIX);
stringValue =stringValue.replace(ESCAPE_FILL_SUFFIX,FILL_SUFFIX);

Copilot uses AI. Check for mistakes.

Comment on lines 40 to 67
public static TemplateStringPart text(String text) {
if (text == null) {
throw new IllegalArgumentException("The text parameter cannot be empty when creating a text part");
}
return new TemplateStringPart(TemplateStringPartType.TEXT, text
, null, null, null);
}

public static TemplateStringPart commonVariable(String variableName) {
if (variableName == null) {
throw new IllegalArgumentException("The variableName parameter cannot be null " +
"when creating a variable part");
}
return new TemplateStringPart(TemplateStringPartType.COMMON_VARIABLE, null
, variableName, null, null);
}

public static TemplateStringPart collectionVariable(String collectionName, String variableName) {
if (variableName == null) {
throw new IllegalArgumentException("The variableName parameter cannot be null " +
"when creating a collection variable part");
}
return new TemplateStringPart(TemplateStringPartType.COLLECTION_VARIABLE, null
, variableName, collectionName, null);
}

public static TemplateStringPart bareCollectionVariable(String variableName) {
return collectionVariable(null, variableName);
Copy link

CopilotAIJul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Theorder field is never set when parts are created, so sorting byorder has no effect. Consider assigning a sequence value toorder in the parser or remove unused ordering logic.

Suggested change
publicstaticTemplateStringParttext(Stringtext) {
if (text ==null) {
thrownewIllegalArgumentException("The text parameter cannot be empty when creating a text part");
}
returnnewTemplateStringPart(TemplateStringPartType.TEXT,text
,null,null,null);
}
publicstaticTemplateStringPartcommonVariable(StringvariableName) {
if (variableName ==null) {
thrownewIllegalArgumentException("The variableName parameter cannot be null " +
"when creating a variable part");
}
returnnewTemplateStringPart(TemplateStringPartType.COMMON_VARIABLE,null
,variableName,null,null);
}
publicstaticTemplateStringPartcollectionVariable(StringcollectionName,StringvariableName) {
if (variableName ==null) {
thrownewIllegalArgumentException("The variableName parameter cannot be null " +
"when creating a collection variable part");
}
returnnewTemplateStringPart(TemplateStringPartType.COLLECTION_VARIABLE,null
,variableName,collectionName,null);
}
publicstaticTemplateStringPartbareCollectionVariable(StringvariableName) {
returncollectionVariable(null,variableName);
publicstaticTemplateStringParttext(Stringtext,Integerorder) {
if (text ==null) {
thrownewIllegalArgumentException("The text parameter cannot be empty when creating a text part");
}
returnnewTemplateStringPart(TemplateStringPartType.TEXT,text
,null,null,order);
}
publicstaticTemplateStringPartcommonVariable(StringvariableName,Integerorder) {
if (variableName ==null) {
thrownewIllegalArgumentException("The variableName parameter cannot be null " +
"when creating a variable part");
}
returnnewTemplateStringPart(TemplateStringPartType.COMMON_VARIABLE,null
,variableName,null,order);
}
publicstaticTemplateStringPartcollectionVariable(StringcollectionName,StringvariableName,Integerorder) {
if (variableName ==null) {
thrownewIllegalArgumentException("The variableName parameter cannot be null " +
"when creating a collection variable part");
}
returnnewTemplateStringPart(TemplateStringPartType.COLLECTION_VARIABLE,null
,variableName,collectionName,order);
}
publicstaticTemplateStringPartbareCollectionVariable(StringvariableName,Integerorder) {
returncollectionVariable(null,variableName,order);

Copilot uses AI. Check for mistakes.

@delei
Copy link
Member

Hi,@Hui-FatGod

We should resolve conflicts first, and please modify the commit message to better comply with the commit guidelines.
e.g.,feat: xxx

@Hui-FatGodHui-FatGod changed the titleAdd support for custom parsing placeholder syntax for template fillingfeature: Add support for custom parsing placeholder syntax for template fillingJul 31, 2025
@Hui-FatGodHui-FatGod reopened thisAug 1, 2025
@Hui-FatGodHui-FatGod changed the titlefeature: Add support for custom parsing placeholder syntax for template fillingfeat: Add support for custom parsing placeholder syntax for template fillingAug 1, 2025
@Hui-FatGod
Copy link
Author

Hi,@Hui-FatGod

We should resolve conflicts first, and please modify the commit message to better comply with the commit guidelines. e.g.,feat: xxx

After I submitted this PR, the fastexcel main branch went through some directory and code style refactoring. To keep things clean, I’ve re-added the original enhancement for custom parser template filling to the latest version of the main branch. Right now, there are no conflicts.

@alaahong
Copy link
Member

Thanks for your contribution. Can you try to merge latest code then resolve the conflicts?

And meanwhile, can you try to add strong unit test with assertions? The sample file ( unconventional.xlsx ) is enough and good for verification, but I can not see the behavior since change executed from ut.

@deleidelei added the PR: require-multiple-approvalsThis pull request requires multiple approvals. labelOct 3, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

Copilot code reviewCopilotCopilot left review comments

@jipengfei-jpfjipengfei-jpfAwaiting requested review from jipengfei-jpf

@psxjoypsxjoyAwaiting requested review from psxjoy

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

PR: require-multiple-approvalsThis pull request requires multiple approvals.

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

3 participants

@Hui-FatGod@delei@alaahong

[8]ページ先頭

©2009-2025 Movatter.jp