Originalmente, queríamos gerar documentos no lado do Android (isso requer ...). No final, não há um bom método que possa ser perfeito no Android e, no final, só podemos mudar para o servidor. Não o desperdice, mas registre as razões pelas quais cada estrutura não suporta o Android e suas características. Ainda existem muitas dessas estruturas relacionadas ao Java, e algumas não são ruins, mas infelizmente elas não suportam o Android ou cobram uma taxa e têm um preço baixo.
Após os testes pessoais, muitos pacotes AWT que não suportam Java não podem ser usados diretamente no Android. O Freemarker é muito bom e pode gerar documentos complexos e bonitos, mas infelizmente não suporta o Android. Ele pode ser executado no Android usando o POI, mas passou por muitas armadilhas ao longo do caminho devido a versão, formato, etc., e ainda é iluminado para abrir com WFS. JWORD e Aspose.word podem ser perfeitamente suportados, e o período de liberdade condicional JWORD é de apenas 30 dias, ambos cobrar para ambos. O ITEXT não tem teste, mas diz -se que não suporta o Android.
Método 1: Freemarker
Este método requer criar manualmente um modelo de documento (lembre -se de usar os espaços reservados para a imagem) e salvá -lo como um arquivo XML. Gerar substituindo dinamicamente o conteúdo na tag específica $ {}. exemplo:
Primeiro, vamos fazer as renderizações:
classe pública Docutil {public Configuration Configuration = null; public Docutil () {Configuration = new Configuration (Configuration.version_2_3_22); configure.SetDefaultEncoding ("UTF-8"); } /*** Gere o arquivo do Word com base no modelo do documento* @param datamap os dados que precisam ser preenchidos no modelo* @param DownloadType Nome do arquivo* @param savepath save path* /public void CreateCoc (map <string> objeto> datamap, string downloadtype, string salvar) {try {// carregar o modelo que precisa de modelo para ser o modelo para ser o modelo para ser o modelo que você não deve ser o modelo, que não é o modelo que você não deve ser o modelo, o modelo de datamap. // Defina o método e o caminho do dispositivo de modelo, o Freemarker suporta vários métodos de carregamento de modelo. Você pode recarregar o servlet, a classe de classe e o suporte do banco de dados. // Carregue o arquivo de modelo e coloque -o em TestDoc Configure.setClassfortemplateLoading (this.getClass (), "/testDoc"); // Defina o Object Wrapper // Configure.SetObjectWrapper (new DefaultObjectWrapper ()); // Defina o manipulador de exceção configure.setTemplateExceptionHandler (templateExceptionHandler.ignore_handler); // Defina o objeto de modelo, observe que o nome do tipo de modelo deve ser consistente com o modelo DownloadType = Configure.getTemplate (DownloadType+". Xml"); Arquivo outfile = novo arquivo (savePath); Escritor out = null; out = new BufferWriter (novo outputStreamWriter (new FileOutputStream (outfile), "UTF-8")); template.process (datamap, out); out.Close (); } catch (ioexception e) {e.printStackTrace (); } catch (modelplateException e) {e.printStackTrace (); }} public string getImageST (string imgfile) {inputStream in = null; byte [] dados = nulo; tente {in = new FileInputStream (imgfile); dados = novo byte [in.Available ()]; in.read (dados); in.Close (); } catch (filenotfoundException e) {e.printStackTrace (); } catch (ioexception e) {e.printStackTrace (); } Base64Encoder coder = new base64Encoder (); return coder.encode (dados); }} classe pública testDoc {public static void main (string [] args) {docutil docutil = new Docutil (); Mapa <string, object> datamap = new hashmap <string, object> (); datamap.put ("Nome", "Joanna"); datamap.put ("ExamNum", "11111111111111"); datamap.put ("Idcard", "222222222222222222222222222222222222222222222222222222222222222 222222222222222222222 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222; datamap.put ("Carmodel", "C1"); docutil.getImageSt ("d: //img//userimg1.png"); datamap.put ("FirstExamscores", "0 pontos, falhou"); DataMap.put ("FirstPic2", Docutil.getImageSt ("d: //img//firstpic2.png")); datamap.put ("SecondExamscores", "90 pontos, passa"); dataMap.put ("SecondDeductItem", ""); datamap.put ("Secondpic1", docutil.getImageST ("d: //img//secondpic1.png")); datamap.put ("Secondpic2", docutil.getImageST ("d: //img//secondpic2.png")); datamap.put ("Secondpic3", docutil.getImageST ("d: //img//secondpic3.png")); Docutil.Createdoc (DataMap, "Basedoc", "d: //yanqiong.doc"); }} O arquivo XML é muito longo, então não vou postar ...
Finalmente, o motivo pelo qual o Android não pode ser usado: http://stackoverflow.com/questions/25929542/use-freemarker-library-in-android
Perguntas adicionais sobre exibição dinâmica de listas e quebras de linha
O requisito é claro: no item de dedução acima, se eu tiver vários itens de dedução, quero que cada quebra de linha seja exibida.
Adicionar linhas de novo diretamente ao conteúdo a ser exibido não tem efeito e não funcionará como uma nova linha.
Ao adicionar tags FTL, como <#list> </list>, surgirão alguns problemas, que não são reconhecidos no XML, resultando na não conseguir ser executada.
resolver:
Adicione e adicione quebras de linha à posição em que vários itens de dedução precisam ser exibidos:
<#List FirstDeductiTem como FirstItem>
<w: t> $ {FirstItem} </w: t> <w: br/>
</#list>
Mude para:
List <string> strs = new ArrayList <String> ();
Strs.add ("111111111111111111");
Strs.add ("2222222222222222222222222222);
Strs.add ("33333333333333");
datamap.put ("primeirodeductiTem", strs);
Altere -o para docutil.java:
// Defina o objeto de modelo, observe que o nome do tipo de modelo deve ser consistente com o download
modelo = configure.getTemplate (DownloadType+". FTL"); No momento, o arquivo XML relatará um erro e, é claro, é impossível compilar e executar o projeto. Você precisa alterar o arquivo .xml para o arquivo .ftl para salvar. Em seguida, compilar e executar, renderizações:
Método 2: POI
Eu encontrei muitos problemas de versão usando esse método. Isso é baseado no POI3.7+Word2007, e o teste pode ser executado perfeitamente.
Você precisa gerar manualmente o modelo de documento com o Word2007 (usando outras gerações, causará um erro: o arquivo não pode ser aberto) e substituir o conteúdo que precisa ser atualizado dinamicamente com $ {}, semelhante ao acima, mas não precisa salvá -lo como um formato de documento XML.
/** * Personalize o método xwpfdocument e substitua createPicture () * @author joanna.yan * */public class CustomXwpfDocument estende o xwpfdocument {public customxwpfdocument (inputStream in) lança ioexception {(in);; } public customxwpfdocument () {super (); } public CustomXwpfDocument (opcpackage pkg) lança ioexception {super (pkg); } public void CreatePicture (int id, int largura, int altura, parágrafo xwpfparagraph) {final int emu = 9525; largura *= emu; altura *= emu; String blipid = ((PoixmlDocumentPart) getAllPictures (). Get (id)). GetPackageRelationShip (). GetId (); Ctinline inline = paragraph.createrun (). Getctr (). AddNewDrawing (). AddNewinline (); String picxml = "" + "<a: xmlns gráfico: a =/" http://schemas.openxmlformats.org/drawingml/2006/main/ ">" + "<a: graphicdata uri =/"http://schemas.openxmlformats.org/drawingml/2006/picture/"> " +" <pic: pic xmlns: pic =/"http://schemas.openxmlFformats.org/drawingml/2006/picture" ") <pic: cnvpr id =/"" + id + "/" name =/"generated/"/> " +" <pic: cnvpicpr/> " +" </pic: nvpicpr> " +" <pic: blipfill> " +" <a: blip r: incorped =/"" + blipid + "/" xmlns: r =/"http://schemas.openxmlformats.org/officedocument/2006/relationships/"/> " +" <a: stretch> " +" <a: filtrect/> " +" </a: stract> "</pic: blipfill>" x=/"0/" y=/"0/"/>" + " <a:ext cx=/"" + width + "/" cy=/"" + height + "/"/>" + " </a:xfrm>" + " <a:prstGeom prst=/"rect/">" + " <a:avLst/>" + " </a:prstGeom>" + " </pic:spPr>" + " </pic: pic> " +" </a: GraphicData> " +" </a: gráfico> "; inline.addnewgraphic (). addNewgraphicData (); XmlToken xmlToken = null; tente {xmltoken = xmltoken.factory.parse (picxml); } catch (xmlexception e) {e.printStackTrace (); } inline.set (xmlToken); inline.setDistt (0); inline.setDistb (0); inline.setDistl (0); inline.setDistr (0); Ctpositivesize2d extension = inline.addnewextent (); extent.setCx (largura); extent.setcy (altura); CtnonvisualDrawingProps docpr = inline.addnewdocpr (); docpr.setId (id); docpr.setName ("imagem"+id); docpr.setDescr ("teste"); }} /** * Adequado para o Word 2007 * POI Versão 3.7 * @author joanna.yan * */public class Wordutil {public static CustomXwpfDocument GenerateWord (map <string, object> param, string modelo) {customxwpdocument doc = null; tente {opcpackage pack = PoixmlDocument.openpackage (modelo); doc = novo customxwpfdocument (pack); if (param! = null & ¶M.Size ()> 0) {// Lista de parágrafos de processamento <xwpfparagraph> paragraphlist = doc.getParagraphs (); Processparagraphs (parágrafos, param, doc); // tabela de processamento iterador <xwpftable> it = doc.gettablesIterator (); while (it.hasnext ()) {xwpfftable tabela = it.next (); Lista <XWPFTabLEROW> linhas = tabela.getRows (); para (xwpftableRow linha: linhas) {list <xwpftableCell> células = row.gettableCells (); para (célula XWPFTableCell: células) {list <xwpfparagraph> paragraphlisttable = Cell.getParagraphs (); Processparagraphs (paragraphlisttable, param, doc); }}}}}} catch (ioexception e) {e.printStackTrace (); } retornar doc; } / ** * Parágrafo do processo * @param paragraphlist * @param param * @param doc * / public static void ProcessParagraphs (list <xwpfparagraph> paragraphlist, map <string, object> param, customxwpfdocument doc) {if (paragrafr! : paragraphlist) {list <xwpfrun> runs = paragraph.getRuns (); para (XWPFRUN RUN: RUNS) {String text = run.getText (0); if (text! = null) {boolean ISSETTEXT = false; para (entrada <string, objeto> entrada: param.entrySet ()) {string key = entradas.getKey (); if (text.indexOf (chave)! =-1) {iSSettext = true; Valor do objeto = Entry.getValue (); if (Value Instânciaof string) {// texto de substituição de texto = text.replace (key, value.toString ()); } else if (Instância do valor do mapa) {// text de substituição de imagem = text.replace (chave, ""); Mapa pic = (mapa) valor; int width = integer.parseint (pic.get ("width"). ToString ()); int height = integer.parseint (pic.get ("altura"). tostring ()); int pictype = getPictureType (pic.get ("type"). tostring ()); byte [] bytearray = (byte []) pic.get ("content"); ByteArrayInputStream byteInputStream = novo byteArrayInputStream (bytearray); tente {int ind = doc.addpicture (byteInputStream, pictype); doc.createPicture (IND, largura, altura, parágrafo); } catch (invalidformatexception e) {e.printStackTrace (); } catch (ioexception e) {e.printStackTrace (); }}}}}} if (ISSETTEXT) {run.settext (texto, 0); }}}}}}}} / ** * Obtenha o código do tipo de imagem correspondente de acordo com o tipo de imagem * @param pictype * @return * / public static int getPictTeType (string pictype) {int res = customxwpdocument.picture_type_pict; if (pictype! = null) {if (pictype.equalsignorecase ("png")) {res = customxwpfdocument.picture_type_png; } else if (pictype.equalsignorecase ("DIB")) {res = customxwpfdocument.picture_type_dib; } else if (pictype.equalsignorecase ("emf")) {res = customxwpfdocument.picture_type_emf; } else if (pictype.equalsignorecase ("jpg") || pictype.equalsignorecase ("jpeg")) {res = customxwpfdocument.picture_type_jpeg; } else if (pictype.equalsignorecase ("wmf")) {res = customxwpfdocument.picture_type_wmf; }} retornar res; }} classe pública testpoi {public static void main (string [] args) lança ioexception {map <string, object> param = new hashmap <string, object> (); param.put ("$ {name}", "joanna.yan"); param.put ("$ {ExamNum}", "0000000000000001"); param.put ("$ {idcard}", "1111111111111111111111111111"); param.put ("$ {carmodel}", "c1"); CustomXwpfDocument doc = wordutil.geReword (param, "d: //joanna.docx"); FileOutputStream FOPTS = new FileOutputStream ("d: //yan.docx"); Doc.Write (FOPTS); fopts.close (); }}O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.