From 2b3f4c8995cce8a3e5e8932d25318a16c866f082 Mon Sep 17 00:00:00 2001 From: whai Date: Thu, 21 Nov 2024 14:54:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(ForJdk17):=20=E6=B7=BB=E5=8A=A0=20LeetCode?= =?UTF-8?q?=20=E9=A2=98=E7=9B=AE=E8=A7=A3=E7=AD=94=E5=92=8C=20Excel=20?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 LeetCode221、LeetCode673 和 LeetCode931 的解答代码 - 实现了每日温度计算和二叉树循环移位算法 - 添加了 Excel 导出用户列表的功能 - 更新了 SpringDemo项目的依赖,增加了 Apache POI- 移除了 TransactionConfig 类的代码 --- .../java/cn/whaifree/interview/Dws/P1.java | 123 +++++++---- .../cn/whaifree/leetCode/LeetCode221.java | 57 +++++ .../cn/whaifree/leetCode/LeetCode673.java | 85 ++++++++ .../cn/whaifree/leetCode/LeetCode931.java | 58 ++++++ SpringDemo/pom.xml | 14 ++ .../springdemo/config/TransactionConfig.java | 194 +++++++++--------- .../workBook/WorkBookController.java | 96 +++++++++ .../template/project_member_workHours.xlsx | Bin 0 -> 10108 bytes 8 files changed, 494 insertions(+), 133 deletions(-) create mode 100644 ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode221.java create mode 100644 ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode673.java create mode 100644 ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode931.java create mode 100644 SpringDemo/src/main/java/cn/whaifree/springdemo/controller/workBook/WorkBookController.java create mode 100644 SpringDemo/src/main/resources/template/project_member_workHours.xlsx diff --git a/ForJdk17/src/main/java/cn/whaifree/interview/Dws/P1.java b/ForJdk17/src/main/java/cn/whaifree/interview/Dws/P1.java index b019d45..f90ecd2 100644 --- a/ForJdk17/src/main/java/cn/whaifree/interview/Dws/P1.java +++ b/ForJdk17/src/main/java/cn/whaifree/interview/Dws/P1.java @@ -1,6 +1,7 @@ package cn.whaifree.interview.Dws; import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; import java.util.*; @@ -15,21 +16,22 @@ public class P1 { class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 - * + *

* 每日温度 + * * @param dailyTemperatures int整型一维数组 * @return int整型一维数组 */ - public int[] temperatures (int[] dailyTemperatures) { + public int[] temperatures(int[] dailyTemperatures) { // write code here // 每一天需要等待几天会出现更高温 // 单调栈 int[] res = new int[dailyTemperatures.length]; Deque stack = new LinkedList<>(); for (int i = 0; i < dailyTemperatures.length; i++) { - while (!stack.isEmpty()&&dailyTemperatures[i] > dailyTemperatures[stack.peek()]) { + while (!stack.isEmpty() && dailyTemperatures[i] > dailyTemperatures[stack.peek()]) { Integer pop = stack.pop(); - res[pop] = i -pop; + res[pop] = i - pop; } stack.push(i); } @@ -42,49 +44,71 @@ public class P1 { class Solution { - static class Node{ - int parentIndex; - int currentIndex; - int flag; - TreeNode currentNode; - public Node(int parentIndex, int currentIndex, int flag, TreeNode currentNode) { + public static void main(String[] args) { + Solution solution = new Solution(); + // {1,2,3,#,#,4,5},1 + TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 3, null, null, 4, 5}); + System.out.println(solution.cyclicShiftTree(treeNode, 1)); + } + + // Node类封装了节点的层次信息,便于后续重构指针 + static class Node { + int parentIndex;// 父节点在当前层的位置 + int currentIndex; // 当前节点在该层的索引位置 + boolean leftFlag; // 标记当前节点是左孩子(0)还是右孩子(1) + TreeNode currentNode; // 当前节点的引用 + + public Node(int parentIndex, int currentIndex, boolean leftFlag, TreeNode currentNode) { this.parentIndex = parentIndex; this.currentIndex = currentIndex; - this.flag = flag; + this.leftFlag = leftFlag; this.currentNode = currentNode; } } + /** * https://blog.csdn.net/ouyang_peng/article/details/143254632 * - * * @param root TreeNode类 - * @param k int整型 + * @param k int整型 * @return TreeNode类 */ - public TreeNode cyclicShiftTree (TreeNode root, int k) { - // write code here + public TreeNode cyclicShiftTree(TreeNode root, int k) { + if (root == null) return null; // + // 存储每层的节点信息,最后用来重构 List> levels = new ArrayList<>(); Queue queue = new LinkedList<>(); - queue.offer(new Node(0,0,0,root)); - int parentNum = 1; - int nextNum = 0; - List tempLevel = new ArrayList<>(); + // 根节点加入队列 + queue.offer(new Node(0, 0, true, root)); - while (!queue.isEmpty()){ + // `parentNum`记录当前层节点数,`nextNum`记录下一层节点数 + int parentNum = 1; // 根节点只有1个节点 + int nextNum = 0; // 层次遍历,每次进入一个到这一层,就++,就能统计这一层的元素个数 + List tempLevel = new ArrayList<>(); // 当前层的节点列表 + + while (!queue.isEmpty()) { Node node = queue.poll(); - tempLevel.add(node); + tempLevel.add(node); // 加入当前层 parentNum--; - if (node.currentNode.left!=null){ - queue.offer(new Node(node.currentIndex,nextNum++,0,node.currentNode.left)); + + if (node.currentNode.left != null) { + queue.offer( + new Node( + node.currentIndex, // 父节点位置, node为父亲节点在当前层的位置 + nextNum++, // 当前节点位置 + true, + node.currentNode.left + ) + ); } - if (node.currentNode.right!=null){ - queue.offer(new Node(node.currentIndex,nextNum++,1,node.currentNode.right)); + if (node.currentNode.right != null) { + queue.offer(new Node(node.currentIndex, nextNum++, false, node.currentNode.right)); } - if (parentNum==0){ + if (parentNum == 0) { + // 每层最后一个元素 parentNum = nextNum; nextNum = 0; levels.add(tempLevel); @@ -92,25 +116,52 @@ class Solution { } } - int depth = levels.size()-1; + int depth = levels.size() - 1; + // 从最底层开始,逐层向上进行位移操作。 + // 对于每一层,首先计算出这一层需要位移的步数,然后根据位移步数调整每个节点的左右子节点指针。 for (int i = depth; i > 0; i--) { - List parentLev = levels.get(i - 1); + List parentLev = levels.get(i - 1); // 上一层的节点 int parentSize = parentLev.size(); + // 这一层节点左右都设置为空 for (Node node : parentLev) { - node.currentNode.left=null; - node.currentNode.right=null; + node.currentNode.left = null; + node.currentNode.right = null; } - int move = k%(2*parentSize); - tempLevel = levels.get(i); + // 计算这一层需要位移的位置,位移后在哪个父节点之下 + // 上一层的个数决定位移个数 + /** + * 比如 + * 1 + \ + 3 + / \ + 4 5 + 第3层的位移个数是根据第二层有几个元素确定的,这个位置和父亲节点的距离为move + */ + int move = k % (2 * parentSize); + tempLevel = levels.get(i); // 本层 for (Node node : tempLevel) { - int targetIndex = node.flag == 0 ? (node.parentIndex + move / 2) % parentSize : (node.parentIndex + (move + 1) / 2) % parentSize; - int targetFlag = node.flag == 0?move%2:(move+1); + int targetIndex = 0; // 在本层的新位置 + if (node.leftFlag) { + targetIndex = (node.parentIndex + move / 2) % parentSize; + } else { + targetIndex = (node.parentIndex + (move + 1) / 2) % parentSize; + } + + + int targetFlag = 0; + if (node.leftFlag) { + targetFlag = move % 2; + } else { + targetFlag = (move + 1) % 2; + } + Node targetP = parentLev.get(targetIndex); - if (targetFlag==0){ + if (targetFlag == 0) { targetP.currentNode.left = node.currentNode; - }else { + } else { targetP.currentNode.right = node.currentNode; } } diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode221.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode221.java new file mode 100644 index 0000000..1b5c126 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode221.java @@ -0,0 +1,57 @@ +package cn.whaifree.leetCode; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/11/20 12:20 + * @注释 + */ +public class LeetCode221 { + + @Test + public void test() { + Solution solution = new Solution(); + System.out.println(solution.maximalSquare(new char[][]{{'1', '0', '1', '0', '0'}, {'1', '0', '1', '1', '1'}, {'1', '1', '1', '1', '1'}, {'1', '0', '0', '1', '0'}})); + } + + class Solution { + /** + * 如果三个位置都为x,那么本节点就是变长为x的 + * + * @param matrix + * @return + */ + public int maximalSquare(char[][] matrix) { + int maxLen = 0; + int[][] dp = new int[matrix.length][matrix[0].length]; + for (int i = 0; i < matrix[0].length; i++) { + if (matrix[0][i] == '1') { + dp[0][i] = 1; + maxLen = 1; + } + } + + for (int i = 0; i < matrix.length; i++) { + if (matrix[i][0] == '1') { + dp[i][0] = 1; + maxLen = 1; + } + } + for (int i = 1; i < matrix.length; i++) { + for (int j = 1; j < matrix[0].length; j++) { + if (matrix[i - 1][j] == '1' && matrix[i][j - 1] == '1' && matrix[i - 1][j - 1] == '1') { + if (matrix[i][j] == '1') { + dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1; + } + } else if (matrix[i][j] == '1') { + dp[i][j] = 1; + } + maxLen = Math.max(maxLen, dp[i][j]); + } + } + return maxLen * maxLen; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode673.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode673.java new file mode 100644 index 0000000..61e8c25 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode673.java @@ -0,0 +1,85 @@ +package cn.whaifree.leetCode; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.function.IntPredicate; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/11/20 12:57 + * @注释 + */ +public class LeetCode673 { + + @Test + public void test() { + // 2 2 2 2 2 + System.out.println(new Solution().findNumberOfLIS(new int[]{1})); + } + + class Solution { + /** + * dp[i] 表示0-i最长递增子序列,子序列长度 + * count[i] 以nums[i]为结尾的字符串,最长递增子序列的个数为count[i] + * + * @param nums + * @return + */ + public int findNumberOfLIS(int[] nums) { + if (nums.length <= 1) return nums.length; + int max = 0; + + int[] dp = new int[nums.length]; + // 初始化 + Arrays.fill(dp, 1); + int[] count = new int[nums.length]; + Arrays.fill(count, 1); + for (int i = 1; i < nums.length; i++) { + int left = i - 1; + while (left >= 0) { + if (nums[left] < nums[i]) { + + if (dp[left] + 1 > dp[i]) { + // 找到一个更长的子序列 + // 那么数量应该为left的count,表示最长递增子序列的个数更新为left处的 + count[i] = count[left]; + } else if (dp[left] + 1 == dp[i]) { + // 如果找到的子序列长度和原来的一样,那么就加上left处的 + // 增加left处的最长递增,因为这时最长递增子序列的长度都一样 + count[i] += count[left]; + } + + dp[i] = Math.max(dp[i], dp[left] + 1); // 最长递增子序列的长度 + } + max = Math.max(max, dp[i]); + left--; + } + + } + + int res = 0; + // 统计所有最长递增子序列的个数为max的 + for (int i = 0; i < nums.length; i++) { + if (dp[i] == max) { + res += count[i]; + } + } + return res; + } + + } +} +class Test989 { + private int a = 10; + int b = 20; + static int c = 30; + + public static void main(String[] args) { + Test989 t = new Test989(); // 创建 Test 类的对象 + System.out.println(t.a); // 错误:a 是 private 的 + System.out.println(t.b); // 正确:b 是实例变量 +// System.out.println(this.c); // 正确:c 是 static 变量 + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode931.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode931.java new file mode 100644 index 0000000..770ca31 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode931.java @@ -0,0 +1,58 @@ +package cn.whaifree.leetCode; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/11/20 11:59 + * @注释 + */ +public class LeetCode931 { + + @Test + public void test() { + Solution solution = new Solution(); + // [[2,1,3],[6,5,4],[7,8,9]] + System.out.println(solution.minFallingPathSum(new int[][]{{2, 1}, {6, 5}})); + } + + class Solution { + /** + * int[i][j] 表示从最顶到i j 的价值 + * + * 第一层为对应格子的值 + * + * 最最左边和最右边只能由 2个推出 + * + * @param matrix + * @return + */ + public int minFallingPathSum(int[][] matrix) { + int n = matrix.length; + int[][] dp = new int[n][n]; + // 第一层 + for (int i = 0; i < matrix.length; i++) { + dp[0][i] = matrix[0][i]; + } + + for (int i = 1; i < n; i++) { + // 每层 , 第一个元素只能由上一个 + dp[i][0] = Math.min(dp[i - 1][0], dp[i - 1][1])+ matrix[i][0]; + for (int j = 1; j < n - 1; j++) { + dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i - 1][j + 1]) + matrix[i][j]; + } + dp[i][n - 1] = Math.min(dp[i - 1][n - 1], dp[i - 1][n - 2]) + matrix[i][n - 1]; + } + + int min = Integer.MAX_VALUE; + for (int i = 0; i < n; i++) { + min = Math.min(min, dp[n - 1][i]); + } + return min; + } + } + +} diff --git a/SpringDemo/pom.xml b/SpringDemo/pom.xml index 4418e5c..07cc19a 100644 --- a/SpringDemo/pom.xml +++ b/SpringDemo/pom.xml @@ -30,6 +30,20 @@ 17 + + + + org.apache.poi + poi + 5.0.0 + + + + org.apache.poi + poi-ooxml + 5.0.0 + + com.github.ben-manes.caffeine diff --git a/SpringDemo/src/main/java/cn/whaifree/springdemo/config/TransactionConfig.java b/SpringDemo/src/main/java/cn/whaifree/springdemo/config/TransactionConfig.java index 3bdbee3..7be3782 100644 --- a/SpringDemo/src/main/java/cn/whaifree/springdemo/config/TransactionConfig.java +++ b/SpringDemo/src/main/java/cn/whaifree/springdemo/config/TransactionConfig.java @@ -1,97 +1,97 @@ -package cn.whaifree.springdemo.config; - -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionManager; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.annotation.TransactionManagementConfigurer; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.transaction.support.DefaultTransactionDefinition; -import org.springframework.transaction.support.TransactionCallback; -import org.springframework.transaction.support.TransactionTemplate; - -import javax.sql.DataSource; - -/** - * @version 1.0 - * @Author whai文海 - * @Date 2024/11/15 16:37 - * @注释 - */ -@Configuration -@Slf4j -public class TransactionConfig implements TransactionManagementConfigurer { - - - @Autowired - private TransactionTemplate transactionTemplate; - - //配置事务管理器 - @Bean - public TransactionManager transactionManager(DataSource dataSource) { - DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource); - // 打印参数 - log.info("transactionManager: {}", transactionManager); - log.info("dataSource: {}", dataSource); - return transactionManager; - } - - @Resource(name="txManager1") - private PlatformTransactionManager txManager1; - - // 创建事务管理器1 - @Bean(name = "txManager1") - public PlatformTransactionManager txManager(DataSource dataSource) { - return new DataSourceTransactionManager(dataSource); - } - - @Override - public TransactionManager annotationDrivenTransactionManager() { - return txManager1; - } - - @Transactional(value="txManager1") - public void addUser() { - - } - - public void addUser2() { - DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); - transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); - transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); - TransactionStatus transaction = txManager1.getTransaction(transactionDefinition); - try { - txManager1.commit(transaction); - } catch (Exception e) { - txManager1.rollback(transaction); - } - } - - /** - * 编程事务 - * TransactionTemplate - * PlatformTransactionManager - * DataSourceTransactionManager - */ - - public void adduser3() { - Object execute = transactionTemplate.execute(new TransactionCallback() { - @Override - public Object doInTransaction(TransactionStatus status) { - return null; - } - }); - } - - -} - -class Tran{ - -} +//package cn.whaifree.springdemo.config; +// +//import jakarta.annotation.Resource; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.jdbc.datasource.DataSourceTransactionManager; +//import org.springframework.transaction.PlatformTransactionManager; +//import org.springframework.transaction.TransactionDefinition; +//import org.springframework.transaction.TransactionManager; +//import org.springframework.transaction.TransactionStatus; +//import org.springframework.transaction.annotation.TransactionManagementConfigurer; +//import org.springframework.transaction.annotation.Transactional; +//import org.springframework.transaction.support.DefaultTransactionDefinition; +//import org.springframework.transaction.support.TransactionCallback; +//import org.springframework.transaction.support.TransactionTemplate; +// +//import javax.sql.DataSource; +// +///** +// * @version 1.0 +// * @Author whai文海 +// * @Date 2024/11/15 16:37 +// * @注释 +// */ +//@Configuration +//@Slf4j +//public class TransactionConfig implements TransactionManagementConfigurer { +// +// +// @Autowired +// private TransactionTemplate transactionTemplate; +// +// //配置事务管理器 +// @Bean +// public TransactionManager transactionManager(DataSource dataSource) { +// DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource); +// // 打印参数 +// log.info("transactionManager: {}", transactionManager); +// log.info("dataSource: {}", dataSource); +// return transactionManager; +// } +// +// @Resource(name="txManager1") +// private PlatformTransactionManager txManager1; +// +// // 创建事务管理器1 +// @Bean(name = "txManager1") +// public PlatformTransactionManager txManager(DataSource dataSource) { +// return new DataSourceTransactionManager(dataSource); +// } +// +// @Override +// public TransactionManager annotationDrivenTransactionManager() { +// return txManager1; +// } +// +// @Transactional(value="txManager1") +// public void addUser() { +// +// } +// +// public void addUser2() { +// DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); +// transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); +// transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); +// TransactionStatus transaction = txManager1.getTransaction(transactionDefinition); +// try { +// txManager1.commit(transaction); +// } catch (Exception e) { +// txManager1.rollback(transaction); +// } +// } +// +// /** +// * 编程事务 +// * TransactionTemplate +// * PlatformTransactionManager +// * DataSourceTransactionManager +// */ +// +// public void adduser3() { +// Object execute = transactionTemplate.execute(new TransactionCallback() { +// @Override +// public Object doInTransaction(TransactionStatus status) { +// return null; +// } +// }); +// } +// +// +//} +// +//class Tran{ +// +//} diff --git a/SpringDemo/src/main/java/cn/whaifree/springdemo/controller/workBook/WorkBookController.java b/SpringDemo/src/main/java/cn/whaifree/springdemo/controller/workBook/WorkBookController.java new file mode 100644 index 0000000..8eb5060 --- /dev/null +++ b/SpringDemo/src/main/java/cn/whaifree/springdemo/controller/workBook/WorkBookController.java @@ -0,0 +1,96 @@ +package cn.whaifree.springdemo.controller.workBook; + +import cn.hutool.http.server.HttpServerResponse; +import cn.hutool.poi.excel.WorkbookUtil; +import com.google.common.collect.Lists; +import jakarta.servlet.http.HttpServletResponse; +import lombok.Data; +import lombok.Setter; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.io.*; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/11/20 16:35 + * @注释 + */ +@Controller +@RequestMapping("/workBook") +public class WorkBookController { + @GetMapping(value = "/exportUser") + public void export(HttpServletResponse response) throws UnsupportedEncodingException { + // WorkBook + response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder + .encode("导出成员工时.xlsx", "UTF-8")); + response.setContentType("application/vnd.ms-excel;charset=utf-8"); + try ( + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template/project_member_workHours.xlsx"); + OutputStream out = response.getOutputStream() + ) { + Workbook query = query(inputStream); + query.write(out); + out.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + public List getUserList() { + List userList = new ArrayList<>(); + for (int i = 0; i < 30; i++) { + User user = new User(); + user.setNickName("张三" + i); + user.setDepartment("研发部"); + user.setFullName("张三" + i); + userList.add(user); + } + return userList; + } + + + public Workbook query(InputStream inputStream) { + Workbook workbook = WorkbookUtil.createSXSSFBook(inputStream); + Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表 + List userList = getUserList(); + for (int i = 0; i < userList.size(); i++) { + Row row = sheet.createRow(i + 1); + + Cell cell = row.createCell(0); + cell.setCellValue(userList.get(i).getNickName()); + + cell = row.createCell(1); + cell.setCellValue(userList.get(i).getFullName()); + + cell = row.createCell(2); + cell.setCellValue(userList.get(i).getDepartment()); + } + return workbook; + } + + @Data + @Setter + static class User { + private String nickName; + private String fullName; + private String department; + } + +} + + diff --git a/SpringDemo/src/main/resources/template/project_member_workHours.xlsx b/SpringDemo/src/main/resources/template/project_member_workHours.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5b4e7826a0c669df30b46203f0f4b1fc92413740 GIT binary patch literal 10108 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