复杂Excel模版定义

模版示例:
复杂Excel模版定义

Demo Excel样例

代码示例:

@Model.model(TestApply.MODEL_MODEL)
@Model(displayName = "测试申请")
public class TestApply extends IdModel {

    public static final String MODEL_MODEL = "top.TestApply";

    @Field.String
    @Field(displayName = "发件人")
    private String addresser;

    @Field.String
    @Field(displayName = "委托单位")
    private String entrustedUnit;

    @Field.String
    @Field(displayName = "付款单位")
    private String payer;

    @Field.String
    @Field(displayName = "付款单位地址")
    private String paymentUnitAdd;
}

模版:

package pro.shushi.pamirs.top.core.temp;

import org.springframework.stereotype.Component;
import pro.shushi.pamirs.file.api.builder.SheetDefinitionBuilder;
import pro.shushi.pamirs.file.api.builder.WorkbookDefinitionBuilder;
import pro.shushi.pamirs.file.api.enmu.ExcelAnalysisTypeEnum;
import pro.shushi.pamirs.file.api.enmu.ExcelDirectionEnum;
import pro.shushi.pamirs.file.api.enmu.ExcelHorizontalAlignmentEnum;
import pro.shushi.pamirs.file.api.model.ExcelWorkbookDefinition;
import pro.shushi.pamirs.file.api.util.ExcelHelper;
import pro.shushi.pamirs.file.api.util.ExcelTemplateInit;
import pro.shushi.pamirs.top.api.model.TestApply;

import java.util.Collections;
import java.util.List;

@Component
public class DemoTemplate implements ExcelTemplateInit {

    public static final String TEMPLATE_NAME = "DemoTemplate";

    @Override
    public List<ExcelWorkbookDefinition> generator() {
        WorkbookDefinitionBuilder builder = WorkbookDefinitionBuilder.newInstance(TestApply.MODEL_MODEL, TEMPLATE_NAME)
                .setDisplayName("测试Demo");

        DemoTemplate.createSheet(builder);

        return Collections.singletonList(builder.build());
    }

    private static void createSheet(WorkbookDefinitionBuilder builder) {
        SheetDefinitionBuilder sheetBuilder = builder.createSheet().setName("测试Demo");

        buildBasicInfo(sheetBuilder);

    }

    private static void buildBasicInfo(SheetDefinitionBuilder builder) {
        //A1:D8:表示表头占的单元格数,范围必须大于实际表头行
        BlockDefinitionBuilder mergeRange = builder.createBlock(TestApply.MODEL_MODEL, ExcelAnalysisTypeEnum.FIXED_HEADER, ExcelDirectionEnum.HORIZONTAL, "A1:D8")
                //预设行
                .setPresetNumber(10)
                //合并哪几个单元格
                .createMergeRange("A1:D1")
                .createMergeRange("A2:D2")
                .createMergeRange("A3:D3")
                .createMergeRange("A4:A6")
                .createMergeRange("B4:B6")
                .createMergeRange("C4:C6")
                .createMergeRange("D4:D5");

                //createHeader创建行,createCell创建单元格,setField指定解析字段,setIsConfig指定为true标记该行是需要解析的值
                mergeRange.createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle()).setIsConfig(Boolean.TRUE)
                .createCell().setField("addresser").setStyleBuilder(ExcelHelper.createDefaultStyle().setWidth(6000)).and()
                .createCell().setField("entrustedUnit").and()
                .createCell().setField("payer").and()
                .createCell().setField("paymentUnitAdd").and()
                .and()

                .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER))
                .createCell().setValue("Demo").and()
                .createCell().and()
                .createCell().and()
                .createCell().and()
                .and()

                //由于该行合并为一个单元格,所以其他可以不设置value
                .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER))
                .createCell().setValue("生效金额").and()
                .createCell().and()
                .createCell().and()
                .createCell().and()
                .and()

                .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.RIGHT))
                .createCell().setValue("金额单位:元").and()
                .createCell().and()
                .createCell().and()
                .createCell().and()
                .and()

                //easyExcel解析不了空行,所以这里写上值。由于上面使用createMergeRange把单元格合并了,并且D列有分割,这里填上每个单元格的值,把合并的单元格填为一样的。
                .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER))
                .createCell().setValue("发件人").and()
                .createCell().setValue("委托单位").and()
                .createCell().setValue("付款单位").and()
                .createCell().setValue("地址").and()
                .and()
                .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER))
                .createCell().setValue("发件人").and()
                .createCell().setValue("委托单位").and()
                .createCell().setValue("付款单位").and()
                .createCell().setValue("地址").and()
                .and()
                .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER))
                .createCell().setValue("发件人").and()
                .createCell().setValue("委托单位").and()
                .createCell().setValue("付款单位").and()
                .createCell().setValue("付款单位地址").and()
                .and()

                .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER))
                .createCell().setValue("合计").and()
                .createCell().and()
                .createCell().and()
                .createCell();
    }

}

注意:链式调用不可以太长,如果太长可以使用参数接一下,否则在编译时可能会导致栈溢出。

Oinone社区 作者:yexiu原创文章,如若转载,请注明出处:https://doc.oinone.top/dai-ma-shi-jian/19462.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (1)
yexiu's avataryexiu数式员工
Previous 2024年11月14日 am10:11
Next 2024年11月19日 pm10:23

相关推荐

  • 如何删除系统权限中默认的首页节点

    场景: 并没有设置过首页的配置,为什么在系统权限这里的配置菜单中却有首页的配置。而且显示当前资源未完成初始化设置,无法配置。这个文章将帮助你删除这个节点。 注意:如果添加了以下代码,后续如果需要使用首页的配置,则需要删除该代码。 扩展权限加载节点: 遍历权限加载的节点,找到需要删除的模块首页节点。删除节点。 @Component @Order(88) @SPI.Service public class MyTestNodeLoadExtend implements PermissionNodeLoadExtendApi { @Override public List<PermissionNode> buildRootPermissions(PermissionLoadContext loadContext, List<PermissionNode> nodes) { //删除 TopModule.MODULE_MODULE 的首页节点。 String homepage = TranslateUtils.translateValues(PermissionNodeLoaderConstants.HOMEPAGE_DISPLAY_VALUE); for (PermissionNode node : nodes) { //如果需要删除多个模块的首页,在这里多加一个逻辑与条件即可。 if (!(node instanceof ModulePermissionNode) || !TopModule.MODULE_MODULE.equals(((ModulePermissionNode) node).getModule())) { continue; } List<PermissionNode> permissionNodes = node.getNodes(); Iterator<PermissionNode> iterator = permissionNodes.iterator(); while (iterator.hasNext()) { PermissionNode permissionNode = iterator.next(); if (ResourcePermissionSubtypeEnum.HOMEPAGE.equals(permissionNode.getNodeType()) && homepage.equals(permissionNode.getDisplayValue())) { iterator.remove(); //如果是删除多个模块首页,这里的return改为break; return nodes; } } } return nodes; } } 看效果:首页节点成功删除。

    2024年12月31日
    1.9K00
  • 推送自定义消息

    项目中添加消息依赖 pro.shushi.pamirs.core pamirs-message-api 调用pro.shushi.pamirs.message.engine.message.MessageSender#sendSystemMail发送系统消息示例: @Action(displayName = "发送消息") public Student sendMessage(Student data){ MessageSender mailSender = (MessageSender) MessageEngine.get(MessageEngineTypeEnum.MAIL_SEND).get(null); String content = "发送自定义消息"; String subject = null; List<Long> userIds = new ArrayList<>(); userIds.add(PamirsSession.getUserId()); PamirsMessage message = new PamirsMessage() .setName(subject) .setSubject(subject) .setBody(content) .setMessageType(MessageTypeEnum.NOTIFICATION); List<PamirsMessage> messages = new ArrayList<>(); messages.add(message); SystemMessage systemMessage = new SystemMessage(); systemMessage.setPartners(userIds.stream().map(i -> (PamirsUser) new PamirsUser().setId(i)).collect(Collectors.toList())) .setType(MessageGroupTypeEnum.SYSTEM_MAIL) .setMessages(messages); mailSender.sendSystemMail(systemMessage); return data; }

    2024年8月19日
    1.7K00
  • 代码示例:快速找到示例代码

    1、图表设计器 数据可视化能加载到的接口,方法上需要加 category = FunctionCategoryEnum.QUERY_PAGE @Model.model(ExpensesIncome.MODEL_MODEL) @Component @Slf4j public class ExpensesIncomeAction { @Function.Advanced(type = FunctionTypeEnum.QUERY,category = FunctionCategoryEnum.QUERY_PAGE) @Function.fun(FunctionConstants.queryPage) @Function(openLevel = {FunctionOpenEnum.API}) public Pagination<ExpensesIncome> queryPage(Pagination<ExpensesIncome> page, IWrapper<ExpensesIncome> queryWrapper) { page = new ExpensesIncome().queryPage(page, queryWrapper); if (page!=null && CollectionUtils.isNotEmpty(page.getContent())) { page.getContent().forEach(a->{ if (a.getBudgetInCome()!=null && a.getBudgetInCome().compareTo(new BigDecimal("0.0"))!=0) { if (a.getRetailAmount()!=null) { a.setInComeRate(a.getRetailAmount().divide(a.getBudgetInCome(),2)); } } }); } return page; } } 2、事务支持 1)对于单个系统(InJvm)/模型内部采用强事务的方式。比如:在库存转移时,库存日志和库存数量的变化在一个事务中,保证两个表的数据同时成功或者失败。2)强事务管理采用编码式,Oinone事务管理兼容Spring的事务管理方式;有注解的方式和代码块的方式。a) 使用注解的方式: @Override @PamirsTransactional public void awardOut(AwardBookOutEmpRecordDetail detail) { List<OutEmpRecordSubjectDetail> subjectDetails = detail.getSubjectDetails(); …… } 重要说明基于注解的事务,Bean和加注解的方法必须能被Spring切面到。 b) 使用编码方式: //组装数据/获取数据/校验 Tx.build(new TxConfig()).executeWithoutResult(status -> { // 1、保存部门数据 deliDepartmentService.createOrUpdateBatch(departments); //2、如果父进行了下级关联设置,处理下级关联设置的逻辑 for (DeliDepartment department : departments) { doDepartSubLink(department); } }); ………… 3)对于分布式事务采用最终数据一致性,借助【可靠消息】或者【Job】的方式来实现。 3、平台工具类使用 3.1 FetchUtil pro.shushi.pamirs.core.common.FetchUtil,重点关注 # 根据Id查询列表 pro.shushi.pamirs.core.common.FetchUtil#fetchMapByIds # 根据Id查询,返回Map pro.shushi.pamirs.core.common.FetchUtil#fetchListByIds # 根据Codes查询列表 pro.shushi.pamirs.core.common.FetchUtil#fetchMapByCodes # 根据Code查询,返回Map pro.shushi.pamirs.core.common.FetchUtil#fetchListByCodes # 根据Entity查询 pro.shushi.pamirs.core.common.FetchUtil#fetchOne 其他更多方法参考这个类的源代码 3.2 ListUtils pro.shushi.pamirs.meta.common.util.ListUtils # 把输入的List,按给定的长度进行分组 pro.shushi.pamirs.meta.common.util.ListUtils#fixedGrouping # 从给定的List中返回特定字段的数组,忽略Null并去重 pro.shushi.pamirs.meta.common.util.ListUtils#transform 4、枚举获取 根据枚举的name获取valueInteger value = ArchivesConfigTypeEnum.getValueByName(ArchivesConfigTypeEnum.class,“status1”);根据枚举的name获取枚举项ArchivesConfigTypeEnum typeEnum = TtypeEnum.getEnum(ArchivesConfigTypeEnum.class, “status1”); 5、Map类型的数据怎么定义,即ttype 为map的字段写法 @Field(displayName = "上下文", store = NullableBoolEnum.TRUE, serialize = JSON) @Field.Advanced(columnDefinition = "TEXT") private Map<String, Object> context; 6、后端获取前端请求中的variables PamirsRequestVariables requestVariables = PamirsSession.getRequestVariables(); 7、为什么有时候调用服务走远程了 1、假设: A模型(modelA)所在的模块(ModuleA) B模型(modelB)所在的模块(ModuleB) 部署方式决定调用方式: 1)部署方式1: ModuleA 和 ModuleB 部署在一个jvm中,此时: modelA的服务/页面去调用 modelB,因为部署在一起,直接走inJvm 2、部署方式2: ModuleA 和 ModuleB 部署在不同的jvm中; modelA的服务/页面去调用 modelB,则会走远程(RPC);此时需要: a)ModuleB 需要开启dubbo服务,且ModuleA 和 ModuleB注册中心相同…

    2024年2月20日
    1.9K00
  • 如何选择适合的模型类型?

    介绍 通过Oinone 7天从入门到精通的模型的类型章节我们可以知道模型有抽象模型、存储模型、代理模型、传输模型这四种。但是在在定义模型的时候我们可能不知道该如何选择类型,下面结合业务场景为大家讲解几种模型的典型使用场景。 抽象模型 抽象模型往往是提供公共能力和字段的模型,它本身不会直接用于构建协议和基础设施(如表结构等)。 场景:猫、鸟都继承自动物这个抽象模型 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.annotation.sys.Base; import pro.shushi.pamirs.meta.base.IdModel; import pro.shushi.pamirs.meta.enmu.ModelTypeEnum; @Base @Model.model(AbstractAnimal.MODEL_MODEL) @Model.Advanced(type = ModelTypeEnum.ABSTRACT) @Model(displayName = "动物") public abstract class AbstractAnimal extends IdModel { public static final String MODEL_MODEL = "demo.AbstractAnimal"; @Field.String @Field(displayName = "名称") private String name; @Field.String @Field(displayName = "颜色") private String color; } package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.model(Cat.MODEL_MODEL) @Model(displayName = "猫") public class Cat extends AbstractAnimal { private static final long serialVersionUID = -5104390780952634397L; public static final String MODEL_MODEL = "demo.Cat"; @Field.Integer @Field(displayName = "尾巴长度") private Integer tailLength; } package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.model(Bird.MODEL_MODEL) @Model(displayName = "鸟") public class Bird extends AbstractAnimal { private static final long serialVersionUID = -5144390780952634397L; public static final String MODEL_MODEL = "demo.Bird"; @Field.Integer @Field(displayName = "翼展宽度") private Integer wingSpanWidth; } 存储模型 存储模型用于定义数据表结构和数据的增删改查(数据管理器)功能,是直接与连接器进行交互的数据容器。 场景:存储模型对应传统开发模式中的数据表,上面例子中的Cat和Birdd都属于传输模型,由于模型定义的注解@Model.Advanced(type = ModelTypeEnum.STORE)默认值就是存储模型,所以一般不用手动指定 代理模型 代理模型是用于代理存储模型的数据管理器能力,同时又可以扩展出非存储数据信息的交互功能的模型。 场景一:隔离数据权限 场景二:增强列表的搜索项 场景三:导入导出的时候增加其他特殊信息 场景四:重写下拉组件的查询逻辑做数据过滤 传输模型 传输模型不会在数据库生成的表,只是作为数据的传输使用,跟传统开发模式中的DTO有一点相似。 场景一:批量处理数据 场景二:处理一些跟数据表无关的操作,如:清理指定业务的缓存、查看一些系统监控信息,可以根据业务信息建立对应的传输模型,在传输模型上创建action动作 场景三:通过传输模型完成复杂页面数据传输

    2024年4月7日
    1.9K00
  • Nacos做为注册中心:如何调用其他系统的SpringCloud服务?

    Oinone项目引入Nacos作为注册中心,调用外部的SpringCloud服务 Nacos可以做为注册中心,提供给Dubbo和SpringCloud等微服务框架使用。 目前Oinone的底层使用的是Dubbo进行微服务的默认协议调用,但是我们项目如果存在需要调用其他系统提供的SpringCloud服务,Oinone其实并没有限制大家去这么写代码。 可以参考Nacos或SpringCloud的官方文档,只要不存在Jar包冲突等场景,很多的扩展其实大家都可以使用。 注意!!!Nacos、SpringCloud、SpringCloudAlibaba是有依赖版本严格要求的:点击查看 具体示例: 一、项目中增加依赖 主pom引入兼容的版本: <dependencyManagement> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.7.RELEASE</version> <!– 目前兼容的版本 –> <type>pom</type> <scope>import</scope> </dependency> </dependencyManagement> 使用模块的pom引入依赖: <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> 二、 配置 application.yml spring: cloud: nacos: discovery: server-addr: localhost:8848 username: nacos password: nacos 三、启动类添加注解 @EnableDiscoveryClient @EnableFeignClients public class NacosConsumerApplication { public static void main(String[] args) { SpringApplication.run(NacosConsumerApplication.class, args); } } 四、验证 创建 Feign Client 接口 import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(name = "nacos-demo") // 指定目标服务的名称 public interface ProviderClient { @GetMapping("/hello") String hello(); } 创建 Controller 调用 Feign Client @RestController public class ConsumerController { private final ProviderClient providerClient; public ConsumerController(ProviderClient providerClient) { this.providerClient = providerClient; } @GetMapping("/hello") public String hello() { return providerClient.hello(); } } 在浏览器中访问 http://localhost:8082/hello你应该会看到服务提供者返回的响应。

    2024年6月4日
    3.4K00

Leave a Reply

Please Login to Comment