1. Antecedentes
O Apache POI é uma API Java que cria e mantém várias APIs Java que cumprem o padrão XML (OOXML) do Office (OOXML) e o formato de documento composto Ole 2 da Microsoft (OLE2). Ele pode ser usado para ler e criar e modificar os arquivos MS Excel usando Java. Além disso, você também pode usar o Java para ler e criar arquivos MS Word e MSpowerPoint. O Apache POI fornece a solução Java Operação Excel (para Excel97-2008).
Gere o arquivo Excel correspondente com base no arquivo JSON no formato especificado. Os requisitos são os seguintes
2. Visualização do efeito
3. Formato de dados
Como é gerar arquivos do Excel, o valor aqui considera gerar um arquivo do Excel no formato XLSX. O cabeçalho de dados multifuncional de dados é considerado usar | Por padrão, e o Colspan Rowspan não é usado como. Se você precisar representar duas colunas e duas linhas, o primeiro formato de cabeçalho de mesclagem da coluna é: a | b, a | C gerado tabela é
| UM | |
| B | C |
O front-end constrói os dados a serem gerados como um arquivo JSON que atende aos requisitos e envios e antecedentes por meio da postagem. Defina o formato JSON de acordo com os requisitos acima da seguinte maneira
{"SaveName": "Gere Excel File Name.xlsx", "UsersTyles": [{"id": "1", // sem duplicação, onde você precisa definir o estilo da célula, pode atribuir diretamente o estilo deste valor "estilo": {"Font": {// Set the Basic Font Format "Blod": "#FF0000", // Nome da cor "Nome": "Microsoft Elegant Black", // Font Name "Hight": 20 // Size}, "FMTSTR": "", // Formato de célula,###_), alinheiro,### 0,00; 0 milímetros "Align": "", // //); inferior central "bordercolor": "", // defina a cor da borda como #ff0000 "bgcolor": "" // define a cor de preenchimento da célula}}], "lençóis": [{"sheetname": "", // sheet name "title": [], // compact Area Title Data "titlemerge": [], [], // title ": [], // Compact Area Data" Title Data " Informações do cabeçalho "dados": [], // Informações sobre dados "datamerge": [], // Dados mesclam informações "pés": [], // Tabela Informações finais "Footmerge": [], // Tabela Fim de informações "img": [] // Informações da imagem, você precisa converter a imagem para base64}]}}Breve descrição
O formato de objeto JSON na matriz da cabeça é
{"Nome": "A | B", // Nome do cabeçalho da tabela, Uso do cabeçalho de várias mesa | Para dividir "Tipo": "STR", // Este tipo de dados do tipo de dados STR NUM, a data também é um tipo numérico no Excel e é exibido como formato de data "campo": "f_field1", // campos alternativos, você não pode usar "estilo": {// este dados da coluna é o padrão de coluna ", ele pode ser um estilo" ou o idoso "ou o valor de idéias, ou o valor do idiota, ou o valor de {////telina, o valor da coluna é o estilo", pode ser um estilo "ou o idoso": {//Terend definido na coluna de coluna ". No pé do título da matriz, os dados da lista podem ser um valor separado, como 1, "a" ou um objeto, quando é um objeto, o formato é
{"value": "", // o valor específico do tipo de célula "": "", // o tipo de célula, o padrão padrão "estilo": {} // o estilo da célula pode ser um objeto de estilo ou o valor de identificação definido nos usuários. Se não estiver definido, a cabeça é o estilo correspondente desta coluna por padrão} Os valores de matrizes TitleMerge, Datamerge e Footmerge são cordas separadas por vírgula, o que significa "Iniciar a linha, a linha final, a coluna de início, a coluna final" e o índice começa a 0. Se houver duas linhas e três colunas de dados no título, agora você precisa mesclar os valores correspondentes de uma linha e duas colunas de dados para serem "0:
O valor na matriz IMG é um objeto, formato
{"Col": 1, // A imagem da coluna Iniciar "linha": 0, // a linha de início "Colspan": 1, // A extensão da coluna, o valor mínimo é 1 "lobo de linhas": 2, // o intervalo de linha, o valor mínimo é 1 "dados": "" // base64 Dados de imagem como: "Dados: imagem/Png; 4. Implementação -chave
Os arquivos do Excel após 07 são na verdade um pacote compactado, com cada folha sendo um arquivo XML, sendo o estilo um arquivo XML, sendo a imagem o arquivo de imagem correspondente e é colocado na pasta de mídia, então a ideia de código é
O portal da função é o seguinte
@OverridePublic void BuildOuttputStream () lança FILEProduceRexception {// Processar folhas de dados JSON de entrada = this.jsondata.getjsonArray (this.sheets); iterator <ject> shopheetter = sheets.iterator (); if (sheets.isempty ()) {this.Responsedata.SterCode (1001); this.Responsedata.SetSuccess (false); this.Responsedata.setrmsg ("nenhum dado pode ser gerado"); tiro novo FileProduceRexception ();} wb = new XSSFWorkbook (); this.jsondata.getjsonArray (this.UsersTyles); this.initUsersTyles (UsersTyles); this.initdefaulttheadStyle (); XSSFSHEET WS; Folha de JsonObject; JsonArray SheetData; Sheettitle JsonArray; JsonArray Sheethead; JsonArray Sheetfoot; JSONArray SheetImgs; Shatchname; int sheetIndex = 0; while (Sheetiter.hasNext ()) {sheet = (jsonObject) Sheetiter.Next (); // Obtenha o nome da planilha SheetName = Sheet.getString (this.sheet_name); WS = WB.Creatheet (); if (stringluils.isnotblank); sheetname);} int sheetrowIndex = 0; sheettitle = sheet.getjsonArray (this.sheet_title); this.setMergeCells (ws, sheet.getjsonArray (this.sheet_title_merge), sheetrowindex); sheetrowIndex = this.createrAndom (ws, sheettitle, sheetrowindex); sheethead = sheet.getjsonArray (this.sheet_head); sheetrowIndex = this.createheadcolumn (ws, sheethead, sheetrowindex); this.setMergucells (ws, sheet.getjsonArray (this.sheet_data_merge), sheetrowIndex); sheetData = sheet.getjsonArray (this.sheet_data); sheetrowindex = this.createTata (ws, shophedata, SheTrowindEx); Sheetfoot = Sheet.getjsonArray (this.sheet_foot); this.setMergeCells (ws, chaphe.getjsonArray (this.sheet_foot_merge), sheetrowIndex); sheetrowIndex = this.createrAndom (ws, sheetfoot, sheetrowIndex); SheetImgs = Sheet.getjsonArray (this.sheet_img); this.setSheetImages (WS, SheetImgs);} // Retorno fluxo de saída Tri tente {byteArrayOutputStream OS = novo byteArrayOutputStream (); wb.Write (OS); this.outStreams.add (os);} catch (ioexception e) {tiro o novo FileProduceRexception (e.getMessage (), e.getcause ());}}Gerar objetos de estilo celular, incluindo alinhamento de fundo de borda de fonte
privado xSSFCellStyle CreateCellStyle (estilo JsonObject) {XSSFCELLSTYLE CellStyle = wb.createCellStyle (); // Definir font jsonObject font = style.getjsonObject (this.style_font); fonts Excelfont = this.cretEfnt (font) (f) (f) (f); {CellStyle.setFont (Excefont);} // UNIFICAÇÃO DE borda Black CellStyle.setBorderBottom (BordersTyle.thin); CellStyle.setBordertop (BordersTyle.thin); CellStyle.setBorderleft (Borderstyle.thinle.thinMellestertherMelle.MerSporrightLeLE.SetDerleft (Borderstyle.thin); CellStyle.setBorderright (BordersTyle.Thin); String borderColor = style.getString (this.border_color); if (stringutils.isnotblank (borderColor)) {xssfcolor xfBorDerColor = new XSSFColor (new cor (integger.parseInt (borderColor.substring (1), 16)); xfborderColor); CellStyle.setBorderColor (Borderside.top, XfborDerColor); CellStyle.setBorDerColor (Borderside.Left, XfBorderColor); CellStyle.Setbordercol (Borderside.righor, xfbordercolor); style.getString (this.background_color); if (stringutils.isnotblank (bgcolor)) {xssfcolor CellBGColor = new XSSFColor (new Color (Integer.ParseInt (BGColor.substring (1), 16))); CellStyle.setFillForeRoundColor (CellBGColor); CellStyle.setFillPattern (FillPatterNtype.solid_foreground);} // alinhamento halignment = style.getString (this.halignment); (StringUtils.isnotblank (Halignment)) CellStyle.Setalignment (Horizontalalignment.valueof (halignment.TOUPPERCASE ()); (Stringutils.isnotblank (valenamento)) CellStyle.SetverticalAlignment (verticalalignment.valueof (valignment.TOUPPERCASE ()); // WRAP AUTROMÁTICO TrueCellStyle.setWrapText (true); // formato string fmt = style.getString (this.fmtString); if (stringutils.isnotblank (fmt)) celularyle.setDataFormat (wb.createTataFormat ().Crie estilos de fonte
Fonte privada createfont (JsonObject fontcfg) {if (fontcfg == null) retorna null; xssfffont font = wb.createFont (); font.setFontName (fontcfg.getString (this.font_name); null) font.setBold (fontBoole.BooleanValue ()); fontBoole = fontcfg.getBoolean (this.font_italic); if (fontboole! = null) fOntCFFG.; ! = null && fontboole.BooleanValue () == true) font.setUnderLine (fontunderline.single.getByteValue ()); curto fontheight = fontcfg.getshort (this.font_height); if (fOnTeight! fontcfg.getString (this.font_color); if (colortr! = null) {font.setColor (novo xssfcolor (new color (integger.parseint (colorstr.substring (1), 16))));} retornar font;}Para processar cabeçalhos de tabela, muitos cabeçalhos de tabela são processados e o | O método de segmentação é usado. O comprimento da cabeça são dados da coluna. Existem vários | Em nome, e você saberá quantas linhas existem no cabeçalho. Portanto, existem várias etapas para o processamento do cabeçalho
private int createheadcolumn (xssfheet ws, jsonArray sheethead, int sheetrowindex) {if (sheethead == null) retorna sheetrowIndex; iterator <jent> headerator = sheetHead.iterator (); jsonObject = null intel; String [colsize]; headcellStylekeys = new string [colsize]; int [] headcollevel = new int [colsize]; string colname = null; string [] colineary = null; int maxlevel = 0; ArrayList <ArrayList <String>> (); while (headiter.hasnext ()) {curhead = (jsonObject) headiter.next (); // lidera o estilo padrão se (curhead.containsKey (this.column_style)) {colstyle = colet.get.get.get.column_style); {headcellStylekeys [colindex] = this.columnstyle_prev+ colindex; this.userStyles.put(headCellStyleKeys[colIndex], this.createCellStyle((JSONObject) colStyle));} else if (this.userStyles.containsKey(colStyle)) {headCellStyleKeys[colIndex] = (String) colStyle;}}// Handle default column width if (curhead.containsKey (this.column_width)) {ws.setDefaultColumnWidth (pixtoexcelwdith (curhead.getIntValue (this.column_width));} // salvar o estilo de coluna se (curhead.containsKey (this.column_type) {///tyings); curhead.getString (this.column_type);} else {hapttypes [colindex] = this.celltypeString;} // manipula o cabeçalho multi-table colname = curhead.getString (this.column_name); colineary = colname.split ("// |); collevel; if (collevel> maxlevel) {maxlevel = collevel;} para (int i = 0; i <collevel; i ++) {if (headvaluelist.size () <= i) {headvaluelist.add (new ArrayList <string> ();} i) {i) .add; ws.getRow (sheetrowIndex + i); if (linha == null) {linha = ws.crerows (sheetrowIndex+i);} headcell = row.createCell (colindex); headcell.setCellValue (colineary [i]); headcell.setCellStyle (this.UsersTyles.get (this.headsty_key); Iterator <ArrayList <String>> a = headValuelist.iterator (); jsonArray headmerge = new jsonArray (); string prev = ""; string current = null; int lRowIndex = 0; int startCol = 0; int mergecol = 0; Araylt <string> coluninfo = nul; 0; prev = ""; columninfo = a.next (); // somente na terceira coluna podemos saber se a primeira e a segunda colunas são mescladas. columnInfo.add (""); iterator <string> b = columnInfo.iterator (); xssfcell lastrowcell = null; while (b.hasnext ()) {current = b.G.GeTrow (); if (lrowindex> 0) {lasTrowCell = wsetRow. (prev.equalsignorecase (atual) && lRowindex == 0) {ws.getRow (sheetrowIndex+lRowIndex) .getCell (startCol) .setCellType (Cell.Cell_Type_blank); MerGecol ++;} mais se (prev.EQUELSIGNORASASERER) e Mergecol ++; StringUtils.isblank (lastrowcell.getStringCellValue ())) {ws.getRow (sheetrowIndex+lRowIndex) .getCell (startCol) .setCellType (Cell.Cell_Type_blank); Mergecol ++;} else (se (mergecol> 0 e {headmerge.add (string.format ("%d,%d,%d,%d", lrowindex, lrowindex, startCol - MerGecol - 1, startCol - 1)); MerGecol = 0;}} startCol ++; prev = dourse;} lRowindex+; (Headcollevel [i] <maxlevel) {// A mesclagem da coluna existe headmerge.add (string.format ("%d,%d,%d,%d", headcollevel [i] - 1, nornowvel - 1, i, i); para (int r = headcollevel [i]; r) .createCell (i) .setCellStyle (this.UsersTyles.get (this.headstyle_key));}}} this.setMergeCells (ws, headmerge, sheetrowIndex); retorna sheetrowindex + maxlevel;}Adicionar imagens, os pontos celulares são usados por padrão e a imagem é fixada na área celular especificada.
private void addimg (xssfheet ws, jsonObject iMg, xssfcreationHelper chelper) {string imgBase64 = img.getString (this.sheet_img_data); if (stringUtils.isblank (imgBase64)) imgbase64.split (","); system.out.println (imgary [0]); byte [] imgbyte = base64.decodeBase64 (imgary [1]); int imgidx = wb.addpicture (imgby, workbook.icture_type_jpeg); ws.createdrawingpatriarch (); xssfclientanchor ancor = chelper.createClientanchor (); int col = img.getIntValue (this.sheet_img_col); int linha = img.getIntValue (this.sheet_img_row); anchor.setcol1 (col); drawImg.createPicture (âncora, imgidx); colspan inteiro = img.getInteger (this.sheet_img_colspan); if (colspan == null) colspan = 1; inteiro); 1; pict.Resize (Colspan, linhas);} 5. Resumo
Desta vez, gerei um arquivo do Excel de estilo rico, passando em objetos JSON e estou mais familiarizado com os documentos do POI Operation Office. Comparado com os documentos de análise do Excel, o formato do arquivo não é necessário para ser considerado ao gerar, como: compatível com o formato de 2003, e a análise de sax grande é considerada. Comparado com a geração do front-end JS de arquivos do Excel, a possibilidade de processamento secundário dos arquivos gerados é aumentada; portanto, na entrada funcional, o método de geração de fluxos binários é adotado. Depois que o arquivo for gerado, você pode continuar enviando emails, carregar FTP e outras operações.
Notas -chave
Ok, o acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.