Multi-level header generation method for generating report based on poi
The multi-level header generation method using POI's ColumnTitleBuilder simplifies the process of creating multi-level headers in Excel reports by dividing it into two steps, enabling efficient and user-friendly header creation.
Patent Information
- Application Number
- CN202411191986.5
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2024-08-28
- Publication Date
- 2024-12-20
AI Technical Summary
Existing report generation tools, such as jxl and easyExcel, require complex operations to create multi-level headers in Excel format.
A multi-level header generation method based on POI (Apache POI) that utilizes the ColumnTitleBuilder object to simplify the process by dividing it into two steps: setting the header with the addColumn method multiple times and generating the header with the build method, using recursive functions to manage multi-level headers.
Simplifies the operation of generating multi-level headers by allowing users to sequentially call methods to add columns and generate headers, reducing complexity and improving efficiency.
Smart Images

Figure CN119167903A_ABST
Abstract
Description
Technical Field
[0001] The present invention relates to the field of data processing, and in particular to a multi-level header generation method based on POI to generate reports. Background Art
[0002] With the development of computer software, data intelligent report products are becoming more and more abundant. Users can use report software to process reports. Data reports are a kind of report document that organizes and displays objective data, statistical data, analytical data and comprehensive information in the form of charts or tables.
[0003] To generate data reports in Excel format, Java has mature open source toolkits: jxl and easyExcel, etc. However, when the generated data report contains multi-level headers, more complicated operations are required. Summary of the invention
[0004] In order to overcome the defects of the prior art, the present invention provides a multi-level header generation method for generating reports based on POI, so as to solve the problem of complex operation of the prior art in generating multi-level headers.
[0005] The technical solution adopted by the present invention to solve the technical problem is: a multi-level header generation method based on POI to generate a report, comprising the following steps:
[0006] S1: Obtain the header data corresponding to the report and form a multi-column and multi-level header data group;
[0007] S2: Based on the ColumnTitleBuilder object, call the addColumn method multiple times to set the table header, where each call to the addColumn method passes in a column of multi-level header data groups;
[0008] S3: Based on the ColumnTitleBuilder object, call the build method to generate a header to form a multi-column multi-level header, wherein the number of columns of the multi-level header is the same as the number of columns of the multi-level header data group.
[0009] Specifically, in step S2, based on the addColumn method, its internal sub-method addColumnTitleChildren(int highIndex,String[]titles,ColumnTitleCell parent,int width) is called to set the header, wherein the parameter highIndex is the current level number in the multi-level header, the parameter titles is all the header data in the multi-level header data group of the same column, the parameter parent is the header data of the previous layer of the current layer being processed, and the parameter width is the width of the current column being processed.
[0010] Preferably, in step S2, the addColumnTitleChildren method includes the following sub-steps:
[0011] S21: Get the highest level number highNumCount of the multi-level header, compare the value of the parameter highIndex plus 1 with the value of the highest level number highNumCount, if it is greater, replace the value of the highest level number highNumCount with the value of the parameter highIndex plus 1, if it is less, keep the value of the highest level number highNumCount unchanged, and then execute step S22;
[0012] S22: Determine whether the value of parent.children in the parameter parent is empty; if so, initialize the value of chlidren in the parameter parent, and then execute step S23; if not, determine whether the name in the last object of the value of parent.children in the parameter parent is the header data titles[highIndex] currently being processed, if not, execute step S23, if yes, execute step S25; parent.children is an element in the parameter parent, which is the sub-header under the header corresponding to the parameter parent, and titles[highIndex] is an element in the parameter titles;
[0013] S23: Initialize the ColumnTitleCell object temp and add it to parent.children of the parameter parent, define the value of the element temp.name in the parameter temp as titles[highIndex], define the value of the element temp.colNumStart in the parameter temp as the value of the current global variable colNumcount, add 1 to the value of highIndex and replace the original value of highIndex, then determine whether titles.length is equal to the replaced value of highIndex, where titles.length is the length of the parameter titles; if yes, execute step S24, if not, execute step S21;
[0014] S24: define temp.width as the value of parameter width, where temp.width is the width of the table header, add 1 to the value of the global variable colNumCount and replace the original value of the global variable colNumCount, and then return;
[0015] S25: After adding 1 to the value of highIndex and replacing the original value of highIndex, determine whether the value of titles.length is equal to the value of highIndex; if so, throw an exception; otherwise, execute step S21.
[0016] It is worth noting that in step S3, when calling the bulid method, it is first determined whether the highest level number highNumCount is greater than 1. If so, it is processed as a multi-level header, otherwise it is processed as a single-level header.
[0017] Preferably, in step S3, if the highest level number highNumCount is greater than 1, the merged area list List is initialized first. <cellrangeaddress>cellRangeAddressList = new ArrayList<>(), and initialize the excel row cache Map<Integer,Row> rowCache=new HashMap<>(highNumCount).
[0018] Specifically, in step S3, based on the build method, call its internal sub-method intbuildColumnTitleCell(Sheet sheet, int startRowNumIndex, int currentRowNumIndex, Map<Integer,Row> rowCache,ColumnTitleCell columnTitleCell,List <cellrangeaddress>cellRangeAddressList) to generate the header; the parameter sheet is the sheet object provided by poi, which represents a sheet in Excel; the parameter startRowNumIndex is the starting row number when the multi-level header is created in the current parameter sheet; the parameter currentRowNumInde is the row number of the header currently being processed; the parameter rowCache is a cache.
[0019] Optionally, in step S3, the buildColumnTitleCell method includes the following sub-steps:
[0020] S31: Get the row object of the current row through rowCache.get(currentRowNumlndex); if there is no row object in the current row, create a row object through rowCache.put(currentRowNumlndex,row) and cache it;
[0021] S32: Determine whether ColumnTitleCell.children is empty, if so, execute step S33, if not, execute step S35;
[0022] S33: Create a cell with the value of ColumnTitleCell.colNumStart as the column number, the row number of the current row and the value of ColumnTitleCell.name as the value in the cell, and then determine whether currentRowNumlndex-startRowNumlndex+1 is less than the highest level number highNumCount, if so, execute step S34, if not, return 1; where currentRowNumIndex is the row number of the multi-header being processed, and startRowNumlndex is the starting row number;
[0023] S34: Calculate the end row number endRowNumlndex=startRowNumlndex+highNumCount-1; record the start row number startRowNumlndex, the end row number endRowNumlndex and the current column number as the merged area in the merged area list List, and then return 1;
[0024] S35: Initialize the variable currentWidthNum=0, where the variable currentWidthNum is used to record the number of columns occupied by the sub-header;
[0025] Then traverse ColumnTitleCell.children, recursively call the buildColumnTitleCell method with each child object in ColumnTitleCell.children, and add the number of columns returned by the call to the variable currentWidthNum;
[0026] Create a cell in the current row with columnTitleCell.colNumStart as the column number and columnTitleCell.name as the value in the cell;
[0027] Use the value of currentRowNumlndex as both the start row and the end row 、 The starting column is columnTitleCell.colNumStart, and the ending column is columnTitleCell.colNumStart+currentWidthNum-1. These are recorded in cellRangeAddressList as the merged area, and the value of currentWidthNum is returned.
[0028] The beneficial effects of the present invention are as follows: in the multi-level header generation method based on poi for generating reports, the ColumnTitleBuilder object has two methods disclosed to the outside: addColumn(int with, String...columnTileNames) and build(int startRowIndex, Sheet sheet); the generation process is divided into two steps: the first step is to call the addColumn(int with, String...columnTileNames) method multiple times to set the header, and the second step is to call the build(int startRowIndex, Sheet sheet) method to generate the header; when the addColumn(intwith, String...columnTileNames) method is called, each time it is called, a column is added, and then the build(intstartRowIndex, Sheet sheet) method is called again, and the first parameter of the build(int startRowIndex, Sheet sheet) method is the starting row number of the header to be generated; the second parameter is the Sheet object to generate the header, which is generated by poi. When using it, the user only needs to call the method addColumn(int with,String…columnTileNames) and pass in the parameters in sequence to generate a multi-level header, thus simplifying the operation. BRIEF DESCRIPTION OF THE DRAWINGS
[0029] Figure 1 It is a flowchart of a multi-level header generation method for generating a report based on POI in one embodiment of the present invention;
[0030] Figure 2 A multi-level header generated by a multi-level header generation method for generating a report based on poi in one embodiment of the present invention;
[0031] Figure 3 A schematic diagram of setting a table header when calling addColumn in one embodiment of the present invention;
[0032] Figure 4 A flowchart of the addColumnTitleChildren method in one embodiment of the present invention;
[0033] Figure 5 It is a schematic diagram of a rule for generating the width of a header in a multi-level header in one embodiment of the present invention;
[0034] Figure 6 A flowchart of a buildColumnTitleCell method in one embodiment of the present invention;
[0035] Figure 7 A schematic diagram of a rule for creating a header width when creating a header in one embodiment of the present invention;
[0036] Figure 8 It is a schematic diagram of the level of the current header in a multi-level header in one embodiment of the present invention. DETAILED DESCRIPTION
[0037] The specific embodiments of the present invention are further described below in conjunction with the accompanying drawings. It should be noted that the description of these embodiments is used to help understand the present invention, but does not constitute a limitation of the present invention. In addition, the technical features involved in the various embodiments of the present invention described below can be combined with each other as long as they do not conflict with each other.
[0038] like Figure 1-8 As shown, a multi-level header generation method based on POI report generation includes the following steps:
[0039] S1: Get the header data corresponding to the report and form a multi-column and multi-level header data group; Figure 2 As shown, the table header has three rows, indicating a three-level table header. From left to right, the first column is name, the second column is gender, the third column is parent-parent 1-name, the fourth column is parent-parent 1-mobile phone number, the fifth column is parent-parent 1-relationship, the sixth column is parent-parent 2-name, and so on;
[0040] S2: Based on the ColumnTitleBuilder object, call the addColumn method multiple times to set the table header, where each call to the addColumn method passes in a column of multi-level header data groups;
[0041] S3: Based on the ColumnTitleBuilder object, call the build method to generate a header to form a multi-column multi-level header, wherein the number of columns of the multi-level header is the same as the number of columns of the multi-level header data group.
[0042] In the multi-level header generation method based on poi report generation, the ColumnTitleBuilder object has two methods exposed to the outside: addColumn(int with, String...columnTileNames) and build(intstartRowIndex, Sheet sheet); the generation process is divided into two steps: the first step is to call the addColumn(intwith, String...columnTileNames) method multiple times to set the header, and the second step is to call the build(intstartRowIndex, Sheet sheet) method to generate the header; when the addColumn(int with, String...columnTileNames) method is called, each call is to add a column, with Figure 2 and 3 For example, when adding the fourth row of data, four columns are added; then the build(int startRowIndex,Sheet sheet) method is called. The first parameter of the build(intstartRowIndex,Sheet sheet) method is the starting row number of the table header to be generated; the second parameter is the Sheet object to generate the table header, which is generated by poi. When using it, the user only needs to call the method addColumn(int with,String…columnTileNames) and pass in the parameters in sequence to generate multi-level table headers, thereby simplifying the operation.
[0043] When using it, the user calls the method addColumn(int with,String…columnTileNames), and passes in the following in sequence: (10,"Name"), (10,"Gender"), (10,"Parent","Parent 1","Name"), (10,"Parent","Parent 1","Phone Number"), (10,"Parent","Parent 1","Relationship"), (10,"Parent","Parent 2","Name"), (10,"Parent","Parent 2","Phone Number"), (10,"Parent","Parent 2","Relationship"), (10,"Interest","Interest 1"), (10,"Interest","Interest 2"), (10,"Interest","Interest 3") and (10,"Remarks"), and you can get Figure 2 The multi-level header shown in Figure 1 is shown in Figure 2, where 10 is the width of the header. Figure 2 As shown, taking the 3rd to 6th columns as an example, it means that the first-level header is "Parent", and there are two sub-headers under "Parent": "Parent 1" and "Parent 2", and both sub-headers have "Name".
[0044] In this example, there are three global variables in the ColumnTitleBuilder object:
[0045] 1. private final ColumnTitleCell columnTitleRoot, used to generate the structured data of the multi-level header; 2. private int highNumCount, used to record the highest number of levels of the header; 3. private intcolNumCount, used to record the number of columns currently added in the first step;
[0046] For the data structure of ColumnTitleCell in private final ColumnTitleCell columnTitleRoot:
[0047] private static class ColumnTitleCell{
[0048] private String name; / / header name
[0049] private int colNumStart; / / The number of rows where the header starts
[0050] private int width; / / The width of the header
[0051] private List <columntitlecell>children; / / Subheaders under this header
[0052] }
[0053] When a ColumnTitleBuilder object is created, a ColumnTitleCell object is created at the same time as the value of the global variable columnTitleRoot of the ColumnTitleBuilder object.
[0054] It is worth noting that in step S2, based on the addColumn method, its internal sub-method addColumnTitleChildren(int highIndex, String[] titles, ColumnTitleCell parent, int width) is called to set the header. In this embodiment, when titles is an array greater than 1, addColumnTitleChildren will recursively call itself to process each element in titles; the parameter highIndex is the current level number in the multi-level header, which is used to distinguish the header data of different levels in the multi-level header data group, and is 0, 1, 2... from top to bottom. Figure 2 For example, parent is level 0, parent 1 is level 1, and so on. The title parameter is all the header data in the multi-level header data group of the same column. The title parameter is an array composed of the header data of all levels from top to bottom in the current column. Figure 2 For example, when addColumn is called for the third time, columnTileNames = ["Parent", "Parent 1", "Name"], columnTileNames will be used as the value of the parameter titles, titles[highIndex] is an element in the parameter titles, which represents the name of the level currently being processed, and the parameter parent is the header data of the previous level of the current level being processed. The parameter parent is the data structure of the header of the previous level of the current level being processed. Figure 3 For example, when the addColum method is called for the fourth time, when addColumnTitleChildren processes "Mobile Number", the value of the parameter parent is the data structure of the table header "Parent 1", parent.children is the element in the parameter parent, and parent.children is [{"Name"}] (at this time, {"Mobile Number"} has not been added to parent.children), and the parameter width is the width of the current column processed.
[0055] Among them, after calling its internal sub-method addColumnTitleChildren(int highIndex,String[]titles,ColumnTitleCell parent,int width), the parameters will be entered first, making the parameter highIndex 0, the parameter titles columnTileNames in the addColumn method, the parameter parent the global variable columnTitleRoot, and the parameter width the width in the addColumn method.
[0056] Optional, such as Figure 4 As shown, in step S2, the addColumnTitleChildren method includes the following sub-steps:
[0057] S21: Get the highest level number highNumCount of the multi-level header, compare the value of the parameter highIndex plus 1 with the value of the highest level number highNumCount, if it is greater, replace the value of the highest level number highNumCount with the value of the parameter highIndex plus 1, if it is less, keep the value of the highest level number highNumCount unchanged, and then execute step S22;
[0058] S22: Determine whether the value of parent.children in the parameter parent is empty (with Figure 3 For example, when the addColum method is called for the fourth time, when addColumnTitleChildren processes "mobile phone number", parent is the data structure of the header "Parent 1", and parent.children contains [{"name"}], and {"mobile phone number"} has not yet been added to parent.children); if so, initialize the value of parent.chlidren in the parameter parent (indicating that the current processing is the first-level header or the first sub-header in the previous level header), and then execute step S23; if not, determine whether the name in the last object of the value of parent.children in the parameter parent is the header data titles[highIndex] currently being processed, if not, execute step S23 (indicating that the current header is different from the previous sub-header and is not merged), if so, execute step S25; wherein parent.children is an element in the parameter parent, which is the sub-header under the header corresponding to the parameter parent, and titles[highIndex] is an element in the parameter titles;
[0059] S23: Initialize the ColumnTitleCell object temp and add it to parent.children of the parameter parent. In a multi-level header, there are multiple sub-headers under the parent header, and each sub-header can have multiple sub-headers. In this way, the data structure of the multi-level header is a tree structure. The object temp is a node being created under the tree structure, and the node is a header. Define the value of the element temp.name in the parameter temp as titles[highIndex], define the value of the element temp.colNumStart in the parameter temp as the value of the current global variable colNumcount, add 1 to the value of highIndex and replace the original value of highIndex, and then judge t is itles.length equal to the value of highIndex after replacement, where titles.length is the length of the parameter titles, the parameter titles is columnTileNames in the addColumn method, columnTileNames is an array and therefore titles.length is the length of the array; if so, execute step S24, if not, set the value of the parameter highIndex to the value of the current highIndex, set the parameter titles to the value of the current titles, set the parameter parent to the value of temp, and set the parameter width to the width in the addColumn method, and then execute step S21 (indicating that the current processing is not the final self-header);
[0060] S24: define temp.width as the value of parameter width, where temp.width is the width of the table header, add 1 to the value of the global variable colNumCount and replace the original value of the global variable colNumCount, and then return;
[0061] S25: After adding 1 to the value of highIndex to replace the original value of highIndex, determine whether the value of titles.length is equal to the value of highIndex; if so, throw an exception (indicating that the current final sub-header is the same as the previous sub-header), if not, set the value of the parameter highIndex to the value of the current highIndex, set the parameter titles to the columnTileNames in the addColumn method, set the parameter parent to the last object in children, and set the parameter width to the width in the addColumn method, then execute step S21 (indicating that the current is not the final sub-header).
[0062] In this embodiment, parent.children is a private List <columntitlecell>Children is defined as the sub-headers under the header; temp initializes a ColumnTitleCell type data structure for the current table.
[0063] by Figure 2 and Figure 3 For example, when adding the fourth column of data, four column headers are added. In addition, the addcolumnTitlechildren method will recursively call itself to process each level in the parameter titles, so the parameter highIndex tells the number of the previous level.
[0064] addColumnTitleChildren is a recursive function. After recursion, if Figure 3 As shown, for example: titles = ["Parent", "Parent 1", "Name"], highIndex is the level of the titles array to be processed, width is the width of the column ["Parent", "Parent 1", "Name"], and parent is the data structure of the previous level header in the recursive process. The previous level is the parent header of the current level header. This data structure is of ColumnTitleCell type.
[0065] The addColumnTitleChildren method in this embodiment first processes an element title in the array corresponding to the parameter titles each time, and creates an object of type ColumnTitleCell for the current parameter title. The value of the name of this object is the element title currently being processed, and the starting number colNumStart of the current header column is recorded at the same time; then the newly created object of type ColumnTitleCell is added to the child header children of the ColumnTitleCell object of the previous layer; then the current ColumnTitleCell object is used as the parent of the next layer, and addColumnTitleChildren is recursively called. When recursively reaching the last element title in the array corresponding to the parameter titles, a new object of type ColumnTitleCell is created for this element title, and not only the value of the name of the object is recorded, but also the width of the addColum method is used as the width of the last level of header, as shown in the figure. Figure 5 , the width of the header of the previous level will be calculated from the width of the header of the next level; the last level header has only one column, so it is necessary to check whether the name of the previous header at the same level is the same as the name of the currently processed header. In addition, when the addColum method calls the addColumnTitleChildren sub-method, the value passed by the parameter parent of the addColumnTitleChildren sub-method is the global variable columnTitleRoot, that is, all level 0 headers are sub-headers of the global variable columnTitleRoot; the subsequent traversal and recursion will start from the sub-header columnTitleRoot.children of the global variable columnTitleRoot.
[0066] by Figure 2 For example, when addColumn(int with,String…columnTileNames) is called to the last data: 10,"Remarks", the data will become the following structure.
[0067] {
[0068] "children":[
[0069] {
[0070] "name":"Name",
[0071] "colNumStart":0,
[0072]
[0073]
[0074]
[0075] {
[0076] Preferably, in step S3, when calling the bulid method, first determine whether the highest level number highNumCount is greater than 1, if so, process it as a multi-level header, otherwise process it as a single-level header. In this embodiment, the processing method of the single-level header is the existing conventional method, which will not be repeated again.
[0077] Specifically, in step S3, if the highest level number highNumCount is greater than 1, the merged area list List is initialized first. <cellrangeaddress>cellRangeAddressList = new ArrayList<>() is used to collect the areas to be merged and initialize the Excel row cache Map<Integer,Row> rowCache = new HashMap<>(highNumCount) is used to collect and cache the created rows.
[0078] It is worth noting that in step S3, based on the build method, the internal sub-method intbuildColumnTitleCell(Sheet sheet, int startRowNumIndex, int currentRowNumIndex, Map<Integer,Row> rowCache,ColumnTitleCell columnTitleCell,List <cellrangeaddress>cellRangeAddressList) to generate the header; the parameter sheet is the sheet object provided by poi, which represents a sheet in excel; the parameter startRowNumIndex is the starting row number when the multi-level header is created in the current parameter sheet; the parameter currentRowNumIndex is the row number of the header currently being processed (the buildColumnTitleCell method is a recursive function); the parameter rowCache is a cache. If the current row has already created a row (poi provides a row object, which represents a row in the current sheet), it will be cached in the rowCache to avoid repeated creation of rows later; the columnTitleCell object is a node under the multi-level header tree structure, so the root node is passed to columnTitleCell when it is first called. When calling recursively, pass a child node in the tree to columnTitleCell, List <cellrangeaddress>cellRangeAddressList = new ArrayList<>(), which is the initialized merged area list.
[0079] Among them, in calling its internal method int buildColumnTitleCell(Sheet sheet,intstartRowNumIndex,int currentRowNumIndex,Map<Integer,Row> rowCache,ColumnTitleCell columnTitleCell,List <cellrangeaddress>cellRangeAddressList), the parameters are first entered, making the parameter sheet the sheet in the build method, the parameter startRowNumIndex the startRowIndex in the build method, the parameter currentRowNumInde the startRowIndex in the build method, and the parameter rowCache the global variable columnTitleRoot. The return value of the buildColumnTitleCell method is of int type, which returns how many columns are currently processed.
[0080] Optional, such as Figure 6 As shown, in step S3, the buildColumnTitleCell method includes the following sub-steps:
[0081] S31: Get the row object of the current row through rowCache.get(currentRowNumlndex); if there is no row object in the current row, create a row object through rowCache.put(currentRowNumlndex,row) and cache it;
[0082] S32: Determine whether ColumnTitleCell.children is empty. If so (indicating that a leaf node of columnTitleRoot has been processed), execute step S33; otherwise, execute step S35; wherein the columnTitleCell object is a node under the multi-level header tree structure, so columnTitleCell.children is the child node under this node.
[0083] S33: Create a cell with the value of ColumnTitleCell.colNumStart as the column number, the row number of the current row and the value of ColumnTitleCell.name as the value in the cell, and then determine whether currentRowNumlndex-startRowNumlndex+1 is less than the highest level highNumCount. If so (indicating that the last row of the multi-level header has been processed), execute step S34. Otherwise, return 1 (indicating that only one column is currently processed); currentRowNumIndex is the row number of the multi-level header being processed. This value is passed in from currentRowNumIndex+1 of the previous level during recursion, and startRowNumIndex is passed in during the initial call; startRowNumlndex is the starting row number;
[0084] S34: Calculate the end row number endRowNumlndex=startRowNumlndex+highNumCount-1; record the start row number startRowNumlndex, the end row number endRowNumlndex and the current column number as the merged area in the merged area list List, and then return 1 (indicating that only one column is currently processed);
[0085] S35: Initialize the variable currentWidthNum=0, where the variable currentWidthNum is used to record the number of columns occupied by the sub-header;
[0086] Then traverse ColumnTitleCell.children, and recursively call the buildColumnTitleCell method with each object child in ColumnTitleCell.children (the parameter sheet and the parameter startRowIndex are returned according to the current values; the parameter currentRowNumIndex is calculated by judging whether the current header object is columnTitleRoot (which can be understood as the root header object). If so, it returns 0, and if not, it returns the current currentRowNumIndex + 1; the parameter rowCache is returned according to the current value, and child is each element in columnTitleCell.children), and the number of columns returned by the call is accumulated to the variable currentWidthNum;
[0087] Create a cell in the current row with columnTitleCell.colNumStart as the column number and columnTitleCell.name as the value in the cell;
[0088] Use the value of currentRowNumlndex as both the start row and the end row 、 The value of columnTitleCell.colNumStart is used as the starting column and the value of columnTitleCell.colNumStart+currentWidthNum-1 is used as the ending column. They are recorded in cellRangeAddressList as the merged area, and the value of currentWidthNum is returned (indicating the number of columns with the value of currentWidthNum currently processed). In the tree structure, only the header corresponding to the leaf node can span multiple rows, and the headers of other child nodes are only one row, so the starting row and the ending row here are the same value: the value of currentRowNumlndex.
[0089] Step S3 is to start creating a multi-level header based on the global variable columnTitleRoot created in step S2. The buildColumnTitleCell method is also a recursive method. When it is first called, columnTitleRoot is used as the value of the parameter columnTitleCell. When recursively, each element in columnTitleCell.children is used as the value of the parameter columnTitleCell. After the buildColumnTitleCell method is executed, the number of columns processed by the current level will be returned to the previous level. The cells of the previous level will get the number to be merged in the current header through the return of the next level: variable currentWidthNum. Figure 2 and 7 As shown, in the next level of "Parent 1", each buildColumnTitleCell method will return 1 after processing, so "Parent 1" is 3 columns wide. Figure 2 The "parent" in the table is 6 columns wide. After calculating the number of columns of each parent header, the column merge area of the current header is obtained by columnTitleCell.colNumStart and currentWidthNum. The parent header has only one column, and the array corresponding to the merge area of each parent header is: (columnTitleCell.colNumStar, columnTitleCell.colNumStar+currentWidthNum-1, current row, current row).
[0090] The last sub-header is only one column wide, and its height is the number of levels of the global multi-level header (highNumCount) minus the number of levels of the current header, such as Figure 8 The name is at level 0, and highNumCount = 3. So the name is three rows high. So the array corresponding to the merged area of the current sub-table header is (columnTitleCell.colNumStar, columnTitleCell.colNumStar, current processing row, current processing row + 3-1). The entire recursive process collects all the merged areas by cellRangeAddressList.
[0091] The embodiments of the present invention are described in detail above with reference to the accompanying drawings, but the present invention is not limited to the described embodiments. For those skilled in the art, various changes, modifications, substitutions and variations of these embodiments are made without departing from the principles and spirit of the present invention, and still fall within the scope of protection of the present invention.< / cellrangeaddress> < / cellrangeaddress> < / cellrangeaddress> < / cellrangeaddress> < / columntitlecell> < / columntitlecell> < / cellrangeaddress> < / cellrangeaddress>
Claims
1. A multi-level header generation method for generating reports based on poi, characterized in that: The following steps are involved: S1: Obtain the header data corresponding to the report and form a multi-column and multi-level header data group; S2: Based on the ColumnTitleBuilder object, call the addColumn method multiple times to set the table header, where each call to the addColumn method passes in a column of multi-level header data groups; S3: Based on the ColumnTitleBuilder object, call the build method to generate a header to form a multi-column multi-level header, wherein the number of columns of the multi-level header is the same as the number of columns of the multi-level header data group.
2. A multi-level header generation method for generating reports based on poi according to claim 1, characterized in that: In step S2, based on the addColumn method, its internal sub-method addColumnTitleChildren(inthighIndex,String[]titles,ColumnTitleCell parent,int width) is called to set the header, wherein the parameter highIndex is the current level number in the multi-level header, the parameter titles is all the header data in the multi-level header data group of the same column, the parameter parent is the header data of the previous layer of the current layer being processed, and the parameter width is the width of the current column being processed.
3. A multi-level header generation method for generating reports based on poi according to claim 2, characterized in that: In step S2, the addColumnTitleChildren method The following steps are included: S21: Get the highest level number highNumCount of the multi-level header, compare the value of the parameter highIndex plus 1 with the value of the highest level number highNumCount, if it is greater, replace the value of the highest level number highNumCount with the value of the parameter highIndex plus 1, if it is less, keep the value of the highest level number highNumCount unchanged, and then execute step S22; S22: Determine whether the value of parent.children in the parameter parent is empty; if so, initialize the value of parent.chlidren in the parameter parent, and then execute step S23; if not, determine whether the name in the last object of the value of parent.children in the parameter parent is the header data titles[highIndex] currently being processed, if not, execute step S23, if yes, execute step S25; parent.children is an element in the parameter parent, which is the sub-header under the header corresponding to the parameter parent, and titles[highIndex] is an element in the parameter titles; S23: Initialize the ColumnTitleCell object temp and add it to parent.children of the parameter parent, define the value of the element temp.name in the parameter temp as titles[highIndex], define the value of the element temp.colNumStart in the parameter temp as the value of the current global variable colNumcount, add 1 to the value of highIndex and replace the original value of highIndex, then determine whether titles.length is equal to the replaced value of highIndex, where titles.length is the length of the parameter titles; if yes, execute step S24, if not, execute step S21; S24: define temp.width as the value of parameter width, where temp.width is the width of the table header, add 1 to the value of the global variable colNumCount and replace the original value of the global variable colNumCount, and then return; S25: After adding 1 to the value of highIndex and replacing the original value of highIndex, determine whether the value of titles.length is equal to the value of highIndex; if so, throw an exception; otherwise, execute step S21.
4. A multi-level header generation method for generating reports based on poi according to claim 3, characterized in that: In step S3, when calling the bulid method, it is first determined whether the highest level number highNumCount is greater than 1. If so, it is processed as a multi-level header, otherwise it is processed as a single-level header.
5. A multi-level header generation method for generating reports based on poi according to claim 4, characterized in that: In step S3, if the highest level number highNumCount is greater than 1, the merged area list List is initialized first. <cellrangeaddress> cellRangeAddressList = new ArrayList<>(), and initialize the excel row cache Map<Integer,Row> rowCache=new HashMap<>(highNumCount).< / cellrangeaddress> 6. A multi-level header generation method for generating reports based on poi according to claim 5, characterized in that: In step S3, based on the build method, call its internal sub-method int buildColumnTitleCell(Sheetsheet, int startRowNumIndex, int currentRowNumIndex, Map<Integer,Row> rowCache,ColumnTitleCell columnTitleCell,List <cellrangeaddress> cellRangeAddressList) to generate the header; the parameter sheet is the sheet object provided by poi, which represents a sheet in Excel; the parameter startRowNumIndex is the starting row number when the multi-level header is created in the current parameter sheet; the parameter currentRowNumInde is the row number of the header currently being processed; the parameter rowCache is a cache.< / cellrangeaddress> 7. A multi-level header generation method for generating reports based on poi according to claim 6, characterized in that: In step S3, the buildColumnTitleCell method includes the following sub-steps: S31: Get the row object of the current row through rowCache.get(currentRowNumlndex); if there is no row object in the current row, create a row object through rowCache.put(currentRowNumlndex,row) and cache it; S32: Determine whether ColumnTitleCell.children is empty, if so, execute step S33, if not, execute step S35; S33: Create a cell with the value of ColumnTitleCell.colNumStart as the column number, the row number of the current row and the value of ColumnTitleCell.name as the value in the cell, and then determine whether currentRowNumlndex-startRowNumlndex+1 is less than the highest level number highNumCount, if so, execute step S34, if not, return 1; where currentRowNumIndex is the row number of the multi-header being processed, and startRowNumlndex is the starting row number; S34: Calculate the end row number endRowNumlndex=startRowNumlndex+highNumCount-1; record the start row number startRowNumlndex, the end row number endRowNumlndex and the current column number as the merged area in the merged area list List, and then return 1; S35: Initialize the variable currentWidthNum=0, where the variable currentWidthNum is used to record the number of columns occupied by the sub-header; Then traverse ColumnTitleCell.children, recursively call the buildColumnTitleCell method with each child object in ColumnTitleCell.children, and add the number of columns returned by the call to the variable currentWidthNum; Create a cell in the current row with columnTitleCell.colNumStart as the column number and columnTitleCell.name as the value in the cell; Use the value of currentRowNumlndex as both the start row and the end row 、 The starting column is columnTitleCell.colNumStart, and the ending column is columnTitleCell.colNumStart+currentWidthNum-1. These are recorded in cellRangeAddressList as the merged area, and the value of currentWidthNum is returned.
