Privacy policyContactsAbout siteOpinionsGitHubDonate
© EVILEG 2015-2018
Recommend hosting
TIMEWEB
Jan. 19, 2019, 10: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

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

26

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

0

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

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);
           } 

0

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

0

Добрый день.

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

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

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

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

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

0

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

0

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

0

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

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

0

Похоже я нашел решение на с++ Тут автор описывает про магическое превращение через буфер обмена средствами 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

0

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

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

0

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

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

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

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

0

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

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

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

0

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

0

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

0

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

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

0

Нашел ссылку на древние типы данных , а тут нынешние их аналоги. Но все равно каое что непоня: что такое : 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?

0

Тут нашел 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 '=' Помогите пожалуйста воспользоваться этим методом.

0

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

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

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

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

0

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

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();

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

0

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

0

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

1

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

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

0

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

1

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

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;
        }

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

1

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

0

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

1

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

wordApplication.dynamicCall("Quit()");
0

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Last comments
Feb. 21, 2019, 12:51 p.m.
Евгений Легоцкой

Иногда CMake приходится перезапускать начисто, не обновляет кэш
R
Feb. 21, 2019, 12:29 p.m.
RandyGallup

Я указал данные строки, т.к. без них у меня вылетала следующая ошибка: By not providing "FindQt5Core.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configurat...
Feb. 21, 2019, 12:08 p.m.
BlinCT

Вот атк выглядит мой проектник, посмотрите его. cmake_minimum_required(VERSION 3.6)project(projecttimer)set(CMAKE_CXX_STANDARD 11)set(CMAKE_AUTOMOC ON)set(CMAKE_AUTORCC ON)find_packa...
Feb. 21, 2019, 12:04 p.m.
BlinCT

Смотрите, если вы используете глобально для проекта -DCMAKE_PREFIX_PATH= то вам не надо уже указывать вот эти строкиset(Qt5Core_DIR "C:/Qt/5.12.1/mingw73_64/lib/cmake/Qt5Core")set(Qt5Gui_DIR...
R
Feb. 21, 2019, 11:54 a.m.
RandyGallup

Даже не запускается. main.cpp у меня точно такой же, как в статье. CMakeLists.txt пришлось немного подправить (прикрепил ниже), т.к. не находились некоторые файлы. cmake_minimum_requi...
Now discuss on the forum
Feb. 21, 2019, 8:58 a.m.
Евгений Легоцкой

Ну у меня координаты передавались в зависимости от положения курсора мыши, а в вам по сути нужно будет аналогичным способом посылать даннные из полей ввода. Так что здесь скорее интерфес...
Feb. 20, 2019, 9:55 p.m.
Евгений Легоцкой

Не до конца понимаю сути вопроса, наверное, нужно увидеть программный код и попытку его применения, но к методам базового класса можно обращаться в наследованном классе через вызов по имени ба...
MU
Feb. 20, 2019, 3:06 p.m.
Maciej Urmański

Yes, ok I have solution! Thank you for directing me about annotate.:) Solution is: users_in = User.objects.filter(joined_users__goal=goal, joined_users__joined=True)
Feb. 20, 2019, 2:40 p.m.
Евгений Легоцкой

Думаю, что ещё можно переопределить mouseReleaseEvent(QMouseEvent* event) у QTableView, который содержит модель и немного поиграться с индексом. Если это индекс, который соответству...
Feb. 20, 2019, 10:34 a.m.
Евгений Легоцкой

Да, так тоже можно. Единственный момент в том, что lupdate не всегда понимает, к какому контексту это дело относится, и может запихать в левый контекст. В небольшом проекте это не критич...
Join us in social networks

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