Jan. 19, 2019, 4:08 a.m.

Как документ RTF конвертировать в HTML

Qt, rtf, HTML, CONVERT

Добрый день.
Как документ RTF конвертировать в HTML?
Могу его открыть и прочитать так:

    QString file = QFileDialog::getOpenFileName(0, "Выберете резюме hh.ru", "", "*.rtf");
    if(!file.isEmpty())
    {
        QFile sFile(file);
        if(sFile.open(QFile::ReadOnly | QFile::Text)){
            QTextStream in(&sFile);
            //QTextDocument textDocument;
            //textDocument = in.readAll().toHtmlEscaped();
            QString text = in.readAll();
            sFile.close();

            ui->ResumeHHTextEdit->setHtml(text);
            qDebug()<<text;
        }
    }

Тут Есть подходящая библиотека. Вот , наверно, нужный dll.
Itenso.Rtf.Converter.Html.dll Itenso.Rtf.Converter.Html.dll
Но не могу его дабавить его к проекту как библиотеку, проект требует только формат .lib

Еще тут есть проект. Но не пойму, как еого использовать.
Помогите пожалуйста.

Virtual hosting with 10 percent discount
Virtual hosting with 10 percent discount
EVILEG offers reliable hosting with a 10% discount for virtual hosting and 5% for VPS
26

хотя как динамическая Itenso.Rtf.Converter.Html.dll подключается

Нашел тут код конвертации:

var
  W: Variant;
begin
  W := CreateOleObject('Word.Application');
  W.Documents.Open('e:\test.rtf',False,False);
  W.ActiveDocument.SaveAs('e:\test.html',wdFormatHTML);
  W.ActiveDocument.CLose;
  W.Quit;
  W := UnAssigned;

но это видимо синтаксис VS.
Помогите пожалуйста переписать под QT.
Наверно это будет примерно так:

 QString resumeFileName = QFileDialog::getOpenFileName(0, "Выберете резюме hh.ru", "", "*.rtf");
    QString saveFile = "C:/Users/MS/Downloads/Test.html";
        if(!resumeFileName.isEmpty())
        {
              QAxObject   wordApplication("Word.Application");
              QAxObject *documents = wordApplication.querySubObject("Documents");              
              //QAxObject *document = documents->querySubObject("Open(const QString&, bool)", resumeFileName, true);
              QAxObject *document = documents->querySubObject("Open(const QVariant&, bool)", resumeFileName, true);
              QAxObject *words = document->querySubObject("Words");
              words->querySubObject("Тут запрос конвертации");

              document->dynamicCall("Close (boolean)", false);
           } 

извиняюсь, код на делфи, но подход наверно правильный.

Добрый день.

Я с ActiveX на Вы полностью до незнакомства. Но если поясните кое-какие моменты, то возможно у меня будет идея, которая вас натолкнёт на нужное русло. Поэтому вопрос такой.

А Вы нашли вообще способ сохранять файлы через QAxObject? Дело в том, что тот код на Дельфи-то конечно отражает алгоритм, но библиотеки-то разные?

Впрочем, если смотреть на то, что вы имеете, то возможно, для запроса конвертации нужно записать что-то подобное.

words->querySubObject("SaveAs('e:\test.html', wdFormatHTML)");

Но не знаю, у вас уже есть какие-нибудь примеры сохранение через QAxObject?

Так тоже не работает, но наверно что то похожее должно заработать.
Что то похожее я видел тут и тут .
Как я понял этот вариант должен работать через библиотеки Word. Запрос querySubObject должен вызвать нужную функцию.

Еще я видиле библиотеки на java и C#, которые могут также конывертировать. Не знаете ли вы, можно ли их использовать?

Бибилотеки Java и С# можно использовать, если они будут добавлены в самостоятельную программу, которая будет работать в консольном режиме. Тогда через QProcess можно будет вызывать данную программу и выполнять конвертирование.

Я бы попытался по возможности распарсить получаемый текст, если там удаётся извлечь хоть что-то, что походит на сколько-нибудь структурированные данные. Конечно, придётся с регулярками повозиться.

Похоже я нашел решение на с++
Тут автор описывает про магическое превращение через буфер обмена средствами Word.
Вот
7925-Rtf2HtmlProj.zip 7925-Rtf2HtmlProj.zip
Вот код автора:

// Rtf2Html.cpp : Defines the entry point for the console application. 
// 
#include "stdafx.h" 
#include "Rtf2Html2.h" 
#include "afxhtml.h" 

CWinApp theApp;  // Win32 App with MFC support 

CRichEditCtrl g_ctlRichEdit;  // the two controls 
CHtmlEditCtrl g_ctlEditHtml; 

// This is needed to load the RichEdit control from a file 
static DWORD CALLBACK  
MyStreamInCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) 
{ 
   CFile* pFile = (CFile*) dwCookie; 
   *pcb = pFile->Read(pbBuff, cb); 
   return 0; 
} 

void LoadRtfFile( LPCTSTR pszFilename ) 
{ 
    wchar_t szFilter[] = L"RTF files (*.rtf)|*.rtf;|" 
                         L"All Files (*.*)|*.*||"; 
    CFileDialog dlg(TRUE,0,pszFilename,6,szFilter ); 
    if ( dlg.DoModal()!=IDOK ) { 
        return; 
    } 
    CFile cf( dlg.GetPathName(),CFile::modeRead ); 

    // CFile cf( pszFilename,CFile::modeRead ); 
    EDITSTREAM es; 
    es.dwCookie = (DWORD)&cf; 
    es.pfnCallback = MyStreamInCallback;  
    g_ctlRichEdit.StreamIn( SF_RTF, es ); // load from the file 
} 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 
{ 
    AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0); 
    AfxInitRichEdit2(); // needed for using CRichEditCtrl 

    CWnd* pWnd = CWnd::GetDesktopWindow(); 
    CRect r(0,0,200,200); 

    g_ctlRichEdit.Create( ES_MULTILINE, r, pWnd, 1111); 
    g_ctlEditHtml.Create( 0,0, r, pWnd, 2222 ); 

    LoadRtfFile( argv[1] );     // read the RTF file into the ctrl  
    g_ctlRichEdit.SetSel(0,-1); // select all in the RTF ctrl 
    g_ctlRichEdit.Copy();       // copy to clipboard 
    g_ctlEditHtml.Paste();      // paste into the Html Edit ctrl 
    g_ctlEditHtml.SaveAs( L"C:\\temp\\test.html");  // save HTML 

    return 0; 
}

Не могли бы вы мне помочь адаптировать это под QT

Call back функцию (MyStreamInCallback) можно так и копировать в проект на Qt, также функцию LoadRtfFile можно так и копировать.

Думаю, что здесь особо адаптировать-то нечего, просто добавить в проект на Qt все те функции, а код в _tmain вынести в какой-нибудь слот.

Попробовал, но QT выдает много ошибок, говорит что не знает : LPCTSTR, CFileDialog, CFile, EDITSTREAM и т.д.
Для того, чтобы это испраить, видимо нужны какие то файлы из MSVC.

Так же нашел библиотеку, скомпилированную на C# .
Там же и примеры на C#.
Вот документация по этой библиотеке.
Подключил эту библиотеку.
Пробую воспользоваться этой библиотекой, пока выходит так:

typedef void (*MyPrototype)(QString);
    MyPrototype OpenDocx = (MyPrototype) rtf2HtmlLib.resolve("OpenDocx");
    MyPrototype ToHtml = (MyPrototype) rtf2HtmlLib.resolve("ToHtml"); 

Помогите пожалуйста разобраться с этим

Для решения этой задачи нужно как-то использовать функцию

public string ConvertFileToString(
    string inputFileName
)
Public Function ConvertFileToString ( _
    inputFileName As String _
) As String

вот только она не статичная и не понятно как создать объект нужного класса

Ну не цепляются C# библиотеки в C++ коде, обратное возможно.

Скажите пожалуйста, что же делать с ошибками незнания: LPCTSTR, CFileDialog, CFile, EDITSTREAM и прочего

Это всё из MFC, нужно заменять на QFileDialog, QFile и т.д. Или подключать соответствующие библиотеки из WinAPI, что априори плохая мысль, если используется Qt. . Не работал с теми библиотеками, только с Qt.

Делать это строчка, за строчкой. А не сразу наскоком.

Нашел ссылку на древние типы данных , а тут нынешние их аналоги.
Но все равно каое что непоня:
что такое : LPCTSTR, CALLBACK (наверно QDialig),IDOK, EDITSTREAM, TCHAR
Код у меня получился (не доработанный) такой:

#ifndef RTFTOHTML_H
#define RTFTOHTML_H

#include <QFile>
#include <QDialog>
// Rtf2Html.cpp : Defines the entry point for the console application. 
// 
//#include "stdafx.h" 
//#include "Rtf2Html2.h" 
//#include "afxhtml.h" 

//CWinApp theApp;  // Win32 App with MFC support 

//CRichEditCtrl g_ctlRichEdit;  // the two controls 
//CHtmlEditCtrl g_ctlEditHtml; 

// This is needed to load the RichEdit control from a file 
static int CALLBACK  
 MyStreamInCallback(int dwCookie, char pbBuff, long long cb, long long *pcb) 
{ 
   QFile* pFile = (QFile*) dwCookie; 
   *pcb = pFile->Read(pbBuff, cb); 
   return 0; 
} 

void LoadRtfFile( LPCTSTR pszFilename ) 
{ 
    wchar_t szFilter[] = L"RTF files (*.rtf)|*.rtf;|" 
                         L"All Files (*.*)|*.*||"; 
    QFileDialog dlg(true,0,pszFilename,6,szFilter ); 
    if ( dlg.DoModal()!=IDOK ) { 
        return; 
    } 
    QFile cf( dlg.GetPathName(),QFile::modeRead ); 

    // QFile cf( pszFilename,QFile::modeRead ); 
    EDITSTREAM es; 
    es.dwCookie = (int)&cf; 
    es.pfnCallback = MyStreamInCallback;  
    g_ctlRichEdit.StreamIn( SF_RTF, es ); // load from the file 
} 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 
{ 
    AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0); 
    AfxInitRichEdit2(); // needed for using CRichEditCtrl 

    CWnd* pWnd = CWnd::GetDesktopWindow(); 
    CRect r(0,0,200,200); 

    g_ctlRichEdit.Create( ES_MULTILINE, r, pWnd, 1111); 
    g_ctlEditHtml.Create( 0,0, r, pWnd, 2222 ); 

    LoadRtfFile( argv[1] );     // read the RTF file into the ctrl  
    g_ctlRichEdit.SetSel(0,-1); // select all in the RTF ctrl 
    g_ctlRichEdit.Copy();       // copy to clipboard 
    g_ctlEditHtml.Paste();      // paste into the Html Edit ctrl 
    g_ctlEditHtml.SaveAs( L"C:\\temp\\test.html");  // save HTML 

    return 0; 
}

#endif // RTFTOHTML_H

помогите пожалуйста до конца разобраться с ним.
И скажите пожалуйста , почему не стоит использовать WinAPI, при работе с QT?

Тут нашел
rtftohtml_win32.zip rtftohtml_win32.zip . Похоже она скомпилированна на С++.
Подключил библиотеку как динамическую.
Теперь пытаюсь воспользоваться методом

char * ConvertString(char * rtfBuf, char * htmlBuf, struct convertOptions opt) 

Пока заготовка такая

typedef void (*MyPrototype)(QString);
    MyPrototype ConvertRtfFileToString = (MyPrototype) rtf2HtmlLib.resolve("ConvertString");
    QString text;
    text = ConvertRtfFileToString("C:/Users/MS/Desktop/Резюме/резюме/отправила - 3334709 - Дмитрий.rtf");

Но выдает ошибку: no viable overloaded '='
Помогите пожалуйста воспользоваться этим методом.

Там в примерах в архиве есть пример определения сигнатуры функции.

typedef int (* cfunc)(char * rtffile, char *outfolder, struct convertOptions);
cfunc ConvertFile;

То есть сигнатура только так может объявляться. Вам нужно передать имя файла, каталог, где он находится и структуру настроек. Иначе никак. Передача QString туда никак не подойдёт.

Думаю, что в документации там есть информация о параметрах в той структуре настроек.

В документации она не описанна, только в примере:

struct convertOptions
{
    int  htmlType;           //0-XHTML, 1- HTML, 2-HTML+CSS
    char title[120];         //Page title   
    char extension[10];      //for example, ".html"
    char fontFace[50];       //for example, "Arial" or "Times New Roman"
    char fontSize[10];       //for example ,"10"
    int  preserveImages;     //0-no, 1 - yes 
    int  preserveFontFace;   //0-no, 1 - yes 
    int  preserveFontSize;   //0-no, 1 - yes 
    int  preserveFontColor;  //0-no, 1 - yes 
    int  preserveHyperlinks;    //0-no, 1 - yes
    int  tableBorders;       //0-invisble, 1 - visible
    int  encoding;           /* Windows_1250=0, Windows_1251=1, Windows_1252=2, Windows_1253=3,
                                Windows_1254=4, Windows_1255=5, Windows_1256=6, Windows_1257=7,
                                Windows_1258=8, ISO_8859_1=9,   ISO_8859_2=10,  ISO_8859_3=11,
                                ISO_8859_4=12,  ISO_8859_5=13,  ISO_8859_6=14,  ISO_8859_7=15,
                                ISO_8859_8=16,  ISO_8859_9=17,  KOI8_R=18,      UTF_8=19    */
    int  htmlParts;          //0-html Complete, 1 - only between <body>..</body>
    char imageFolder[500];   //folder where image will be stored
    char cssStyleName[120];  //style name, for example "ts"
    int  fontSizesType;      //0-normal sizes, 1 - medium sizes, 2 - big sizes, 3 - huge sizes
    char imageSubfolder[120];//will create subfolder for storing images, if ""-empty string then images will be strored in 'image_folder' 
    int  hyperlinkTarget;    //0 - no target, 1 - target="_blank",  2 - _self, 3 - _parent, 4 - _top
    int  cssStartNumber;     //number for style name, like a .tsN (.ts1 or .ts100)
    char Serial[12];
};

На этой строчке

ConvertFile=(cfunc)GetProcAddress(rtf2HtmlLib,"ConvertFile");

Выдает ошибку : no matching function for call to 'GetProcAddress'

попробовал сделать так и программа зависла

ypedef int (* cfunc)(char * rtffile, char *outfolder, struct convertOptions);
    cfunc ConvertFile;


    int ret;
    char rtffile[_MAX_PATH];
    char outfolder[_MAX_PATH];

    //load library
    //HINSTANCE rtf2HtmlLib=LoadLibrary("Sautinsoft.RTFToHTML.Win32.dll");

    /*if(rtf2HtmlLib==NULL)
    {
      printf("Unable to load library\n");
      getchar();
      //return 0;
    }*/
    //ConvertFile=(cfunc)GetProcAddress(rtf2HtmlLib,"ConvertFile");

    //typedef void (*MyPrototype)(QString *rtfFile, QString *outFolder, struct convertOptions);
    //MyPrototype ConvertFile = (MyPrototype) rtf2HtmlLib.resolve("ConvertFile");


    /*if (ConvertFile==NULL)
    {
        printf("Can't load function.\n");
        FreeLibrary((HMODULE)rtf2HtmlLib);
        getchar();
        //return 0;
    }*/
    //
    printf("Please enter rtf file (example: d:\\my.rtf):\n");
    gets(rtffile);
    printf("Please enter output folder (example : d:\\temp):\n");
    gets(outfolder);

    //set conversion params
    struct convertOptions ct;
    ct.cssStartNumber=1;
    strcpy(ct.cssStyleName,"ts");
    ct.encoding=9;
    strcpy(ct.extension,".htm");
    strcpy(ct.fontFace,"Verdana");
    strcpy(ct.fontSize,"10");
    ct.htmlType=1;
    ct.preserveFontColor=1;
    ct.preserveFontFace=1;
    ct.preserveFontSize=1;
    ct.preserveImages=1;
    ct.preserveHyperlinks=1;
    ct.tableBorders=1;
    ct.htmlParts=0; //only between <body>...</body>
    strcpy(ct.title,"My Page");
    strcpy(ct.imageFolder,"D:\\");
    strcpy(ct.imageSubfolder,"test.files");
    ct.hyperlinkTarget=0;
    strcpy(ct.Serial,"Serial number");


    ret=ConvertFile("C:/Users/MS/Desktop/Резюме/резюме/отправила - 3334709 - Дмитрий.rtf","C:/Users/MS/Desktop/Резюме/резюме",ct);

    switch(ret)
    {
        case -1 : puts("Check your serial number");break;
        case 0 : puts("Conversion completed");break;
        case 2 : puts("Not enough memory"); break;
        case 3 : puts("Can't open output file"); break;
        case 4 : puts("Can't open input file"); break;
        case 5 : puts("The input file has zerow length"); break;
        default: break;
    }
    //flushall
    getchar();

Помогите пожалуйста разобраться с этой библиотекой

Только если на выходных гляну, у самого своих проектов до кучи, чтобы разбираться в рабочие дни с незнакомой библиотекой.

Зарание спасибо.
А еще на эту тему можно будет сделать статью. Это контент будет уникальным.

А вы случаем ту библиотеку не планируете подключать в приложение на Андроид?

И вообще использовать ActiveX на андроиде?

нет, не планирую

  • Jan. 25, 2019, 7:44 a.m.
  • The answer was marked as a solution.

вот именно так работает конвертация:

QVariant fileFormat(0x0000000A);     //Saving as filtered html
    QString resumeFileName; //= QFileDialog::getOpenFileName(0, "Выберете резюме hh.ru", "", "*.rtf");
    resumeFileName = "C:\\Users\\MS/Downloads\\Абсент.docx";
    QString saveFile = "C:\\Users\\MS/Downloads\\Test.html";
        if(!resumeFileName.isEmpty())
        {
              QAxObject   wordApplication("Word.Application");
              QAxObject *documents = wordApplication.querySubObject("Documents");

              QAxObject *document = documents->querySubObject("Open(const QVariant&, bool)", resumeFileName, true);
              document->querySubObject("SaveAs(const QVariant&,const QVariant)", saveFile, fileFormat);


              document->dynamicCall("Close (boolean)", false);



              qDebug()<<resumeFileName;
        }

конвертирует через ворд

Я вас поздравляю. Приятно наблюдать за прогрессом.

Пожалуй, я тогда не буду заниматься той библиотекой. Всё равно она какая-то мутная на первый взгляд.

и еще в конце нужно дописать для закрытия процесса (иначе будет в памяти висеть):

wordApplication.dynamicCall("Quit()");

Comments

Only authorized users can post comments.
Please, Log in or Sign up
D
Aug. 16, 2019, 11:58 a.m.
Damir

C++ - Тест 003. Условия и циклы

  • Result:92points,
  • Rating points8
D
Aug. 16, 2019, 11:46 a.m.
Damir

C++ - Test 005. Structures and Classes

  • Result:75points,
  • Rating points2
u
Aug. 14, 2019, 1:55 p.m.
unrealproro

C++ - Test 005. Structures and Classes

  • Result:83points,
  • Rating points4
Last comments
Aug. 19, 2019, 6:41 a.m.
Andrej Jankovich

это проблема дистрибутива, попробуйте установить через пакетный менеджер snap Суть проблемы: libQt5Core которая лежит в дистрибутиве требует версию glibc >= 2.25 у вас видимо …
b
Aug. 18, 2019, 5:09 a.m.
bbb116

cqtdeployer /home/aleks/CQtDeployer/bin/cqtdeployer: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.25' not found (required by /home/aleks/CQtDeployer/lib/libQt5Core.so.5) linux mint …
D
Aug. 17, 2019, 8:04 a.m.
Damir

github ChekableTView Правой групповая смена значения при перетаскивании левой как обычно.
Aug. 16, 2019, 12:03 p.m.
Evgenij Legotskoj

Потому, что в минуте 60 секунд
Aug. 16, 2019, 11:16 a.m.
Dmitrij

а почему делитель 60000, а не 1000?
Now discuss on the forum
Aug. 19, 2019, 10:29 a.m.
Aleksej Vnukov

я в дороге, по тому примеру что в есть выше вам чтоб заработало нужно примерно следующее ListModel{ id: list_model } в ListView добавить model:list_model там где кноп…
Aug. 19, 2019, 8:47 a.m.
Pavel K.

bool YourClass::chekIfEmpty(const QString& table) { return getCount(table) == 0;}int YourClass::getCount(const QString& table, const QString& where) { QString command =…
Aug. 19, 2019, 8:29 a.m.
Pavel K.

посмотрите тут , практически тоже самое делал(пробегал по документу). А так в принципе : QFile file(Path);if(file.exist){ file.open(QIODevice::WriteOnly); // ReadWrite for…
Aug. 19, 2019, 2:39 a.m.
grig_p

Здравствуйте! Хотелось бы в своем приложении сделать цетрализованную обработку исключительных ситуаций для их логирования. Переопределил метод notify(): static const int EC_MAINLOOP…
Aug. 15, 2019, 2:19 a.m.
Mihailll

Плюсы и qml отличаются, с++ логичней
Looking for a Job?
14,000.00 руб. - 40,000.00 руб.
Разработчик Qt
Annino, Moscow Oblast, Russia
5,000.00 руб. - 15,000.00 руб.
Дизайнер
Moskovskiy, Moscow, Russia
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

EVILEG
About
Services
© EVILEG 2015-2019
Recommend hosting TIMEWEB