• Курсы Академии Кодебай, стартующие в мае - июне, от команды The Codeby

    1. Цифровая криминалистика и реагирование на инциденты
    2. ОС Linux (DFIR) Старт: 16 мая
    3. Анализ фишинговых атак Старт: 16 мая Устройства для тестирования на проникновение Старт: 16 мая

    Скидки до 10%

    Полный список ближайших курсов ...

интеграция с Aspose

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 953
610
BIT
277
Aspose - библиотека для разных ЯП, обеспечивает работу с документами МСО , в контекста домины ЯП - java
Для подключения лицензии в коде - требуются на доступ к локальной ФС (не знаю зачем)
для агентов - вариант безвыходный - делать разрешения как по ссылке (в jvm/lib/ext/security/java.policy), для хэпагесов - можно ограничится внесением конкретной БД /opt/ibm/domino/notes/latest/linux/jvm/lib/security/java.pol (в винде - анкологично) и перезапуском http
запись вида:
grant codeBase "xspnsf://server:0/<path>/dbName.nsf/-" {
permission java.security.AllPermission;
};
учитывая что имя базы кейссенситив и еще надо добавить по RID
grant codeBase "xspnsf://server:0/__XXXX6B580044XXXX.nsf/-" {
permission java.security.AllPermission;
};
из хэпагов доступ к лицензии через Resources/Files
1564060351144.png

код для получения лицензии:
Java:
    public FindAndReplace() throws Exception {
        license = new com.aspose.words.License();
        InputStream is = //new FileInputStream("Aspose.Total.Java.lic");
                FacesContextEx.getCurrentInstance().getExternalContext().getResourceAsStream("Aspose.txt");
        license.setLicense(is);//"/tmp/Aspose.Total.Java.lic");
    }
рекомендуют засовывать в статик, но учитывая время жизни в домине и особенности GC язассал ;)
сама библиотека "шустрая" и многофункциональная: конвертация в разные форматы из МСО, высокоуровневые ф-ции поиска и замены, OCR (движок КМК tesseract), конкатенация документов, выдергивание текста, баркоды
Есть отображалка в хтмл и редактор (базовый) - это , я его не смотрел
Чем меня подкупил продукт:
- корректный конвертор в ПДФ (проверял на тестовой лицензии и здесь писал)
- скорость
- удобство и подробная документация
цена на тек. 3к енотов версии Total Small Business - за локейшн (меня засмущала формулировка и я даже переписывался с поддержкой), этот вариант - когда рабочие места и движок (интегрированный в программу) в одном здании! (кол-во серверов и приложений ничем не ограничены)
 
Последнее редактирование:
  • Нравится
Реакции: VladSh

VladSh

начинающий
Lotus Team
11.12.2009
1 791
157
BIT
133
А что такое FacesContextEx? Я так понимаю, оно из Resources/Files напрямую получает файл?
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 953
610
BIT
277
А что такое FacesContextEx? Я так понимаю, оно из Resources/Files напрямую получает файл?
напрямую это как? В контексте хэпаги оттуда и FacesContext
в агенте - своя история будет (там в ресурсы агента пихать надо)
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 953
610
BIT
277
еще будет закономерный вопрос - а как с xdocrepot, ибо aspose призван заменить его...
абисняю: нужно будет поменять "легенду" изменить движок на , теги, понятно, придется заменить в файлах ;)
возможностей и гибкости добавится, и не нужны будут "поля" в ворде (и MailMerge)
 
Последнее редактирование:

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 953
610
BIT
277
работа с таблицами...
никуда не деватся от "особенностей" формата, а именно от вложенности вордовых объектов, НО есть высокоуровневая ф-ция замены по регулярному выражению, либо замена таблицы целиком из документа
В последнем варианте получалось лучше чем в КОМ - форматирование под существовавшую (хотя - может я КОМ плохо умею готовить ;) )
примеры на java (в классе ф-ции InsertDocument и ReplaceRowText)
Java:
package com.setralubs;

import com.aspose.words.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class FindAndReplace {
    final com.aspose.words.License license;
    static final String DATA_DIR = "res/";

    public FindAndReplace() throws Exception {
        license = new com.aspose.words.License();
        license.setLicense("Aspose.Total.Java.lic");
    }
    void replace(Document doc, String regex, Map<String,String> map) throws Exception {
        FindReplaceOptions options = new FindReplaceOptions();
        options.setReplacingCallback(new ReplaceEvaluator(map));

        doc.getRange().replace(Pattern.compile(regex), "", options);
        String outName= DATA_DIR + "Range.ReplaceWithEvaluator_Out.docx";
        doc.save(outName);
        Runtime.getRuntime().exec("gio open "+outName);
    }

    /**
     *
     * @param regex
     * @return map as name->[default value,comments]
     * @throws Exception
     */
    Map<String,String[]> getFields(Document doc, String regex) throws Exception {
        String dataDir="res/";
        FindReplaceOptions options = new FindReplaceOptions();
        Map<String,String[]> map=new HashMap<String, String[]>();
        options.setReplacingCallback(new FindEvaluator(map));
        doc.getRange().replace(Pattern.compile(regex), "", options);
        return map;
    }
    public void tablesProcess(Document doc) throws Exception {
        // Table manipulations
        // Get the first table in the document.
        Table firstTable = (Table) doc.getChild(NodeType.TABLE, 0, true);
        NodeCollection<Table> tables=doc.getChildNodes(NodeType.TABLE, true);
        for(Table tbl:tables){
            System.out.println(tbl.getTitle());
            //tbl.getRows().clear();
        }
// We will split the table at the third row (inclusive).
        Row row = firstTable.getRows().get(1);

// Create a new container for the split table.
        Table table = (Table) firstTable.deepClone(false);

// Insert the container after the original.
        firstTable.getParentNode().insertAfter(table, firstTable);

// Add a buffer paragraph to ensure the tables stay apart.
        firstTable.getParentNode().insertAfter(new Paragraph(doc), firstTable);

        Row currentRow;
        //System.out.println(row.getText());
        do {
            currentRow = firstTable.getLastRow();
            table.prependChild(currentRow);
        } while (currentRow != row);
        replaceRows(firstTable,table);
        //firstTable.remove();
    }

    public List<String> getTablesNames(Document doc){
        List<String> lst=new ArrayList<String>();
        @SuppressWarnings("unchecked")
        NodeCollection<Table> tables=doc.getChildNodes(NodeType.TABLE, true);
        for(Table tbl:tables){
            if (!tbl.getTitle().isEmpty())lst.add(tbl.getTitle());
        }
        return lst;
    }

    public Map<String,Table> getTablesNamesMap(Document doc){
        Map<String,Table> map=new HashMap<String, Table>();
        @SuppressWarnings("unchecked")
        NodeCollection<Table> tables=doc.getChildNodes(NodeType.TABLE, true);
        int i=0;
        for(Table tbl:tables){
            String name=tbl.getTitle();
            if (!name.isEmpty()){
                if(map.containsKey(name))name+="+"+i;
                map.put(name, tbl);
            }
            i++;
        }
        return map;
    }

    public List<WordTable> getTables(Document doc){
        List<WordTable> ret=new ArrayList<WordTable>();
        @SuppressWarnings("unchecked")
        NodeCollection<Table> tables=doc.getChildNodes(NodeType.TABLE, true);
        int i=0;
        for(Table tbl:tables){
            ret.add(new WordTable(tbl.getTitle(), tbl));
        }
        return ret;
    }

    public void replaceRows(Table firstTable, Table secondTable) throws Exception {
        firstTable.getRows().clear();
        while (secondTable.hasChildNodes())
            firstTable.getRows().add(secondTable.getFirstRow());
        //replace cell text
        //firstTable.getLastRow().getLastCell().getRange().replace(Pattern.compile(".*"),"new Text");
    }
    public void replaceRowsText(Table firstTable, Table secondTable) throws Exception {
/*
        for (Cell cell : (Iterable<Cell>) firstTable.getChildNodes(NodeType.CELL, true))
            cell.getRange().delete();// removeAllChildren();
*/
        RowCollection rows=secondTable.getRows();
        int cnt=rows.getCount();
        Row lastRow=firstTable.getLastRow();
        Row appendRow=(Row)lastRow.deepClone(true);
        lastRow.getParentNode().insertAfter(appendRow,lastRow);
        int i=0;
        for(Row row:firstTable.getRows()){
            if (i>=cnt) break;
            CellCollection cells=rows.get(i).getCells();
            int c=cells.getCount();
            int j=0;
            for(Cell cell:row.getCells()){
                cell.getRange().replace(".*",j<c?cells.get(j).getText():"");
                j++;
            }
            i++;
        }
    }

    //https://docs.aspose.com/display/wordsjava/How+to++Insert+a+Document+into+another+Document
    public void insertDocument(Node insertAfterNode, Document srcDoc) throws Exception {
        // Make sure that the node is either a paragraph or table.
        if ((insertAfterNode.getNodeType() != NodeType.PARAGRAPH) & (insertAfterNode.getNodeType() != NodeType.TABLE))
            throw new IllegalArgumentException("The destination node should be either a paragraph or table.");

        // We will be inserting into the parent of the destination paragraph.
        CompositeNode dstStory = insertAfterNode.getParentNode();

        // This object will be translating styles and lists during the import.
        NodeImporter importer = new NodeImporter(srcDoc, insertAfterNode.getDocument(), ImportFormatMode.KEEP_SOURCE_FORMATTING);

        // Loop through all sections in the source document.
        for (Section srcSection : srcDoc.getSections()) {
            // Loop through all block level nodes (paragraphs and tables) in the body of the section.
            for (Node srcNode : (Iterable<Node>) srcSection.getBody()) {
                // Let's skip the node if it is a last empty paragraph in a section.
                if (srcNode.getNodeType() == (NodeType.PARAGRAPH)) {
                    Paragraph para = (Paragraph) srcNode;
                    if (para.isEndOfSection() && !para.hasChildNodes())
                        continue;
                }

                // This creates a clone of the node, suitable for insertion into the destination document.
                Node newNode = importer.importNode(srcNode, true);

                // Insert new node after the reference node.
                dstStory.insertAfter(newNode, insertAfterNode);
                insertAfterNode = newNode;
            }
        }
    }
    public Table getTableByName(String name, Document doc){
        Table ret=null;
        NodeCollection<Table> tables=doc.getChildNodes(NodeType.TABLE, true);
        for(Table tbl:tables) {
            String title = tbl.getTitle();
            if (!title.isEmpty() && title.equalsIgnoreCase(name)) {
                ret=tbl;
                break;
            }
        }
        return ret;
    }

    public static void main(String[] args) throws Exception {
        FindAndReplace obj=new FindAndReplace();
        Document doc = new Document(DATA_DIR + "add4_test.docx");
/*
        Sender sender = new Sender();
        sender.setName("LINQ Reporting Engine");
        sender.setMessage("Hello World");

        // Create a Reporting Engine.
        ReportingEngine engine = new ReportingEngine();

        // Execute the build report.
        engine.buildReport(doc, sender, "sender");
        obj.tablesProcess(doc);
        obj.getTablesNamesMap(doc);
*/
        Document doc1=new Document(DATA_DIR + "receivers.doc");
        Table tbl1=obj.getTables(doc).get(0).table;
        Table tbl2=obj.getTables(doc1).get(0).table;
        //obj.replaceRowsText(tbl1, tbl2);
        obj.insertDocument(tbl1,doc1);
        tbl1.remove();
        // save
        String outName=DATA_DIR + "out.docx";
        doc.save(outName);
        Runtime.getRuntime().exec("gio open "+outName);
        System.exit(0);

        obj.getFields(new Document(DATA_DIR + "SpA_SupAgreement.docx"), "(<.+?>)");
        Map<String,String> map=new HashMap<String, String>();
        map.put("<SPA_POSITION>","Генерал");
        map.put("<SPA_WHOM>","Кузнецов");
        obj.replace(new Document(DATA_DIR + "SpA_SupAgreement.docx"), "(<.+?>)", map);
    }
}
в main использование
Вызов КОМы в ЛС для "аналогии"
Код:
Function ReplaceTablesName(NDC As NotesDocumentCollection, worddoc As Variant) As Boolean
    On Error GoTo ErrH
    Dim tblsList List As String
    Dim fname As String, doc As NotesDocument
    Set doc=NDC.GetFirstDocument
    Dim i As Integer
    'перебираем документы таблиц, выгружаем файлы, заполняем список
    Do While Not doc Is Nothing
        Dim fList List As String
        Erase fList
        fname=DetachDocFiles(doc, {}, fList)
        '       Print doc.UniversalID
        If Len(fname)>0 Then
            tblsList(UCase(doc.GetItemValue(NAME_FIELD)(0)))=fname
            '           Print {table name:} &doc.GetItemValue(NAME_FIELD)(0)
            i=i+1
        End If
        Set doc=NDC.GetNextDocument(doc)
    Loop
    If i<1 Then Print {table files doesn't exist}:Exit Function 'не трогать таблицы - если нет файлов
    i=0
    Dim rngS
    'ищем заголовки в таблицах
    Dim tblsObjList List As Variant
    Print {Tables Count:} &CStr(worddoc.Tables.Count)
    Dim cnt As Long, ctbl As Long, tbln As Variant
    For ctbl=1 To worddoc.Tables.Count
        '   Forall tbl In worddoc.Tables
        cnt=cnt+1
        Dim s As String
        s={}
        Set tbln=worddoc.Tables(ctbl)
        On Error Resume Next
        s=UCase(tbln.Title)
        On Error GoTo ErrH
        If Len(s)>0 Then
            Set tblsObjList(s)=tbln
            Print {Search table for replace:} &s
            If IsElement(tblsList(s)) Then
                fname=tblsList(s)
                If Len(fname)>0 Then
                    rngS = tbln.Range.Start
                    tbln.Delete
                    Call worddoc.Range(rngS, rngS).InsertFile(fname,,False)
                    Print {replaced:} s {; iteration:} cnt {; Tables Count:} worddoc.Tables.Count
                    i=i+1
                End If
            End If
        End If
        '   End Forall
    Next
    If i>0 Then Print {Tables with title exist}:Exit Function
    'алгоритм для замены в старом формате Word (не было tbl.Title)
    Dim tbls() As String
    Print {tables w/o titles}
    ReDim Preserve tbls(i) As String 'чтобы не обрабатывать исключение в цикле
    'формируем массив из списка (для старого способ обработки)
    ForAll m In tblsList
        ReDim Preserve tbls(i) As String
        tbls(i)=m
        i=i+1
    End ForAll
    i=0
    ForAll tbl In worddoc.Tables
        fname={}
        If Not i>UBound(tbls) Then
            If Len(tbls(i)) >0 Then fname=tbls(i)
            If Len(fname)>0 Then
                rngS = tbl.Range.Start
                tbl.Delete
                Call worddoc.Range(rngS, rngS).InsertFile(fname,,False)
            End If
        End If
        i=i+1
    End ForAll
    ReplaceTablesName=True
Quit:
    Exit Function
ErrH:
    RaiseError
    Resume Quit
End Function
 
Последнее редактирование:
  • Нравится
Реакции: alexas1

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 953
610
BIT
277
еще для сравнения поиска и замены текста в КОМе
Код:
Function ReplaceByTemplate(replacementList List As String, worddoc As Variant) As Boolean
    On Error GoTo ErrorHandler
    Dim wObj As Variant
    Dim rngToSearch As Variant
    Dim rngResult As Variant
    Dim i As Long
    Dim s As String, txt As String
    
    Set wObj = worddoc.Application
    Set rngToSearch = worddoc.Content
    ForAll m In replacementList
        Set rngResult = rngToSearch.Duplicate
        '       s=defDelim.GetEscLeft() & Listtag(m) & defDelim.GetEscRight()
        '       s={\<} & Listtag(m) & {\>}
        s=ListTag(m)
        rngResult.Find.Text = s
        rngResult.Find.Forward = True
        rngResult.Find.Wrap = wdFindStop
        'не действует MachCase=False для шаблона \<fld_name\>
        rngResult.Find.MatchCase = False'MSWord ...
        '       rngResult.Find.MatchWholeWord = False
        rngResult.Find.MatchWildcards = True
        txt=CStr(m)
        rngResult.Find.Replacement.Text=txt
        rngResult.Find.Execute ,,,,,,,,,,wdReplaceAll
'       Do While rngResult.Find.Execute()
'           i = i + 1
'           rngResult.Select
'           worddoc.Application.Selection.Text=m
'           rngResult.Collapse 0 'wdCollapseEnd
'       Loop
        i=i+1
        DbgMsg({Значение:} & ListTag(m) & ", #" & CStr(i))
    End ForAll
    
    ReplaceByTemplate=True
Quit:
    Exit Function
ErrorHandler:
    Dim se As String
    se=RaiseError()
    Print {#} & Format(i, {000000}) & { ;replace value>} & s & { ;by value>} & txt
    Error Err, se & Chr(10) &Format(i, {000000}) & { ;replace value>} & s & { ;by value>}_
    & Chr(10) &txt
    Resume Quit
End Function
поиск будет вываливать ошибку при длинных строках (чисто вордовская заморочка)
 
  • Нравится
Реакции: alexas1
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!