# Grade-Calculate **Repository Path**: fromdrowning/grade-calculate ## Basic Information - **Project Name**: Grade-Calculate - **Description**: 学业表现分计算程序是一个可以实现读取期末成绩Excel文件、计算读取到的成绩、输出计算结果Excel文件,全部流程在1秒内自动化执行完成的程序,不再需要人工花费大量时间计算学业表现分并一个一个录入电脑中去。同时该程序通过一定的设计,实现在原有代码的基础上自定义读取方法,以及读取完后执行的事件。 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-03-01 - **Last Updated**: 2024-08-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: Java, POI ## README # 学业表现分计算程序(Grade-Calculate) ## 简介 学业表现分计算程序是一个可以实现读取期末成绩Excel文件、计算读取到的成绩、输出计算结果Excel文件,全部流程在1秒内自动化执行完成的程序,不再需要人工花费大量时间计算学业表现分并一个一个录入电脑中去。同时该程序通过一定的设计,实现在原有代码的基础上自定义读取方法,以及读取完后执行的事件。 ## 文件结构 ``` - grade.calculate ├── config // 配置启动的参数 ├── constant // 常量 ├── event // 读取方法完成后执行的事件 ├── listener // 监听器 ├── log // 日志输出 ├── pojo // 封装数据的JavaBean ├── read // 读取Excel文件 - resources // 存放需要读取的Excel文件 - pom.xml // 依赖管理 ``` ## 运行流程 ![image-20240301145454924](.\assets\image-20240301145454924.png) ## 运行环境 - JDK >= 1.8 - Maven >= 3.0 - IDEA中安装有Lombok插件 **注意**程序需要在**没有中文的路径**下运行,以免读取不到文件。 如果您的IDEA没有Lombok插件,可以在插件库中下载 ![image-20240229210901610](.\assets\image-20240229210901610.png) *建议使用17版本的JDK,如果使用的不是17版本需要在启动前将pom.xml和IDEA中的项目结构修改为当前JDK版本* 将**pom.xml**修改为当前JDK版本 ```xml 修改为当前JDK的版本 修改为当前JDK的版本 ``` 将IDEA**项目**的**SDK**和**语言级别**修改为当前JDK版本 ![image-20240229210314249](.\assets\image-20240229210314249.png) 将IDEA**模块**的**语言级别**修改为当前JDK版本 ![image-20240229210235450](.\assets\image-20240229210235450.png) ## 运行程序 ### 快速运行 在run方法写入以下代码即可启动程序。 - **setEventAfterRead** 设置**读取方法完成后执行的事件** 会按照**添加的顺序执行** - **setInputFileName** 设置需要读取Excel的**文件名** 文件要放在resources下并带上**文件后缀** - **setSemesterCourseList** 设置**本学期所有需要计算学业表现分的课程** - **start** 程序启动方法 使用**默认Read读取方法** **注意**在创建Write对象时传入的是**Excel文件输出路径**,如果设置有**多个输出事件**,注意**输出的地址不能重复** ,否则后面输出的Excel文件会**覆盖**先输出的Excel文件。 ```java public class Run { public static void main(String[] args) { Configure.builder() .setEventAfterRead(new Calculate()) .setEventAfterRead(new Write("E:\\测试.xlsx")) .setInputFileName("21软件工程4班.xls") .setSemesterCourseList( "大学英语(4)", "B/S项目实训", "Web编程技术", "系统分析与设计Systems-Analysis-and-Design", "数据库系统原理与应用", "马克思主义基本原理概论", "大学体育专项二(2)", "商业统计Business-Log", "数据库系统原理与应用课程设计") .start(); } } ``` 当看到控制台输出 **运行完成 结束程序** 即可在设置好的输出路径查看输出的Excel文件 ![image-20240229214207380](.\assets\image-20240229214207380.png) ![image-20240301125100436](.\assets\image-20240301125100436.png) ### 可选参数 如果您对快速运行的结果不满意,程序还提供了一些可选的方法来调整输出结果。 - **setListener** 设置**事件监听器** 默认**初始化**了一个**ReadListener监听器** - **setScale** 设置计算结果**保留的小数位数** 默认**保留两位小数** - **setSheetNum** 设置读取**Excel文件的表** 默认**第一张表** - **setOutputSheetName** 设置输出的**表名** 默认表名为**学业表现分排名** **注意**setListener方法必须在设置事件setEventAfterRead方法**前**设置,否则程序会**抛异常**。 ```java public class Run { public static void main(String[] args) { Configure.builder() .setListener(new 自定义监听器类()) // 可选参数 .setEventAfterRead(new Calculate()) .setEventAfterRead(new Write("E:\\测试.xlsx")) .setScale(Scale.TWO) // 可选参数 .setSheetNum(Num.FIRST_SHEET) // 可选参数 .setOutputSheetName("自定义表名") // 可选参数 .setInputFileName("21软件工程4班.xls") .setSemesterCourseList( "大学英语(4)", "B/S项目实训", "Web编程技术", "系统分析与设计Systems-Analysis-and-Design", "数据库系统原理与应用", "马克思主义基本原理概论", "大学体育专项二(2)", "商业统计Business-Log", "数据库系统原理与应用课程设计") .start(); } } ``` ## 程序拓展 如果您需要自定义程序,程序提供了一系列接口。 ### 自定义监听器 如果您需要自定义监听器,请在**listener包**下创建自定义监听器类并**实现Listener接口**。 ```java public class 自定义监听器类 implements Listener { /** * 添加事件 * * @param event 读取方法执行完后需要执行的事件 */ @Override public void addEventAfterRead(Event event) { // 自定义逻辑 } /** * 通知所有事件 *

读取方法执行完后 此方法会被调用 按照添加事件的顺序 运行事件的run方法

* * @param data {@link Data}中可以获取到启动时配置的参数和其它事件处理结果数据 */ @Override public void notifyAllEvent(Data data) { // 自定义逻辑 } } ``` 写好自定义监听器后您可以在运行程序的代码上调用**setListener方法**并将自定义的监听器放入。 ```java public class Run { public static void main(String[] args) { Configure.builder() .setListener(new 自定义监听器类()) // 放入自定义监听器 .setEventAfterRead(new Calculate()) .setEventAfterRead(new Write("E:\\测试.xlsx")) .setInputFileName("21软件工程4班.xls") .setSemesterCourseList( "大学英语(4)", "B/S项目实训", "Web编程技术", "系统分析与设计Systems-Analysis-and-Design", "数据库系统原理与应用", "马克思主义基本原理概论", "大学体育专项二(2)", "商业统计Business-Log", "数据库系统原理与应用课程设计") .start(); } } ``` 如果不想单独创建一个自定义监听器类的文件也可以直接在**setListener方法**上使用**匿名内部类**。 ```java public class Run { public static void main(String[] args) { Configure.builder() .setListener(new Listener() { // 使用匿名内部类 @Override public void addEventAfterRead(Event event) { // 自定义逻辑 } @Override public void notifyAllEvent(Data data) { // 自定义逻辑 } }) .setEventAfterRead(new Calculate()) .setEventAfterRead(new Write("E:\\测试.xlsx")) .setInputFileName("21软件工程4班.xls") .setSemesterCourseList( "大学英语(4)", "B/S项目实训", "Web编程技术", "系统分析与设计Systems-Analysis-and-Design", "数据库系统原理与应用", "马克思主义基本原理概论", "大学体育专项二(2)", "商业统计Business-Log", "数据库系统原理与应用课程设计") .start(); } } ``` ### 自定义读取 如果您需要自定义读取,请在**read包**下创建自定义读取类并**继承AbstractRead类**。 **注意**自定义读取类必须写**传入参数为Data的构造方法**并在构造方法内通过**super(data)**获取**启动时配置的参数**和* *其它事件处理结果数据**。 ```java public class 自定义读取类 extends AbstractRead { /** * 带参构造方法 *

* 通过super(data)获取到启动时配置的参数和其它事件处理结果数据 初始化资源 *

* * @param data {@link Data}用于各个事件之间获取数据 */ public 自定义读取类(Data data) { super(data); // 没写super(data) 继承AbstractRead类的字段值将为空 } /** * 读取方法 */ @Override protected void read() { // 自定义逻辑 } } ``` 写好自定义读取类后您可以在运行程序的代码上调用**start方法**并将自定义的读取类放入。 ```java public class Run { public static void main(String[] args) { Configure.builder() .setEventAfterRead(new Calculate()) .setEventAfterRead(new Write("E:\\测试.xlsx")) .setInputFileName("21软件工程4班.xls") .setSemesterCourseList( "大学英语(4)", "B/S项目实训", "Web编程技术", "系统分析与设计Systems-Analysis-and-Design", "数据库系统原理与应用", "马克思主义基本原理概论", "大学体育专项二(2)", "商业统计Business-Log", "数据库系统原理与应用课程设计") .start(new 自定义读取类()); // 放入自定义读取类 } } ``` ### 自定义事件 如果您需要自定义事件,请在**event包**下创建自定义事件类并**实现event接口**。 ```java public class 自定义事件类 implements Event { /** * 读取方法执行完后 监听器会按照添加事件的顺序 运行run方法 * * @param data {@link Data}中可以获取到启动时配置的参数和其它事件处理结果数据 */ @Override public void run(Data data) { // 自定义逻辑 } } ``` *如果您的自定义事件是**输出类型的事件**并且有**多个输出事件**或**多次调用**,建议在**构造方法**时就传入**输出地址** ,避免因**输出地址重复**而导致后面输出的Excel文件**覆盖**先输出的Excel文件。* ```java public class 自定义输出事件类 implements Event { /** * 带参构造方法 * * @param outputFilePath 文件输出路径 */ public 自定义输出事件类(String outputFilePath) { this.outputFilePath = outputFilePath; } /** * 读取方法执行完后 监听器会按照添加事件的顺序 运行run方法 * * @param data {@link Data}中可以获取到启动时配置的参数和其它事件处理结果数据 */ @Override public void run(Data data) { // 自定义逻辑 } } ``` 写好自定义事件后您可以在运行程序的代码上调用**setEventAfterRead方法**并将自定义的事件放入。 ```java public class Run { public static void main(String[] args) { Configure.builder() .setEventAfterRead(new 自定义事件类1()) // 放入自定义事件 .setEventAfterRead(new 自定义事件类2()) // 放入自定义事件 .setEventAfterRead(new 自定义事件类3()) // 放入自定义事件 .... // 可以无限添加事件 读取方法执行完后 监听器会按照添加事件的顺序 运行事件的run方法 .setInputFileName("21软件工程4班.xls") .setSemesterCourseList( "大学英语(4)", "B/S项目实训", "Web编程技术", "系统分析与设计Systems-Analysis-and-Design", "数据库系统原理与应用", "马克思主义基本原理概论", "大学体育专项二(2)", "商业统计Business-Log", "数据库系统原理与应用课程设计") .start(); } } ``` 如果不想单独创建一个自定义事件类的文件也可以直接在**setEventAfterRead方法**上使用**匿名内部类**并优化为更为简便的* *lambda**。 ```java public class Run { public static void main(String[] args) { Configure.builder() .setEventAfterRead(data -> { // 自定义逻辑 }) .setInputFileName("21软件工程4班.xls") .setSemesterCourseList( "大学英语(4)", "B/S项目实训", "Web编程技术", "系统分析与设计Systems-Analysis-and-Design", "数据库系统原理与应用", "马克思主义基本原理概论", "大学体育专项二(2)", "商业统计Business-Log", "数据库系统原理与应用课程设计") .start(); } } ``` ## 其它 由于个人能力有限,程序中可能会有bug和不足,欢迎大家在仓库上提出issue以及宝贵的意见! 程序仓库地址:https://gitee.com/fromdrowning/grade-calculate.git