寻求Delphi中RTF文件和DOC文件的转换方法?(100分)

  • 主题发起人 主题发起人 another_benlei
  • 开始时间 开始时间
A

another_benlei

Unregistered / Unconfirmed
GUEST, unregistred user!
问题提出:
在Memo中录入文字时要录入公式或图表或图片等并保存到数据库(SQL SERVER2000)的Image字段中->使用RxRichEdit代替Memo,数据能够按RTF文件格式正常存入Image字段中,也能读出显示->引出检索问题->使用SQL Server 2000 的全文检索功能进行检索->发现该死的M$的SQL SERVER2000 基于Image字段的全文检索仅支持Text格式Doc格式.PPT格式,XML格式,而RxRichEdit好像又不支持DOC文件->从而想到把RxRichEdit的数据以DOC格式存入Image字段中,显示时转成RTF格式
考虑到问题难度(怕问题最后不了了之),若有那位仁兄帮我解决该问题,我将另给200分的酬谢!
 
doc转rtf好办,用delphi的Srvers里的控件,打开一个doc文档,全部拷入剪切板,粘
贴到RxRichEdit里保存文件即为为RTF文档。(打开doc的方法有许多,可自己检索一下)。
其他可参看这个帖子:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1417366
 
HunterTeam:
你说的方法我知道,但是我想要的不是你的方法,不过DOC->RTF的方法我已经找到了
下面把方法(该方法转自jlutt-sadan DFW)贴出来,以供大家参考:
================================================================================
其实 安装Office的时候有安装“文本转换器”(好像是这个)
然后到以下路径找找
C:/Program Files/Common Files/Microsoft Shared/TextConv
会看到一堆文件 这里是一些文件相互转换的链接库
其中Word2000(以上)->rtf 使用MSWRD832.CNV
Excel->rtf 使用EXCEL32.CNV
Html->rtf 使用html32.cnv
其它的我还没有测试过
使用的时候 将这些文件拷贝到你的程序路径下 直接用就行了 不需要安装Word
但是我还没有找到不用安装Word 将Rtf转成Doc的方法 唉
下面是我的一个程序中使用的单元
unit Converters;

interface

uses
Registry, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, FileCtrl, OleCtrls, ComCtrls, ExtCtrls, AxCtrls,RVEdit;

// -----------------------------------------------------------------
// Functions to call when you want to convert something
// -----------------------------------------------------------------

// Function to import a file to a WideString.
function ImportAsRTF(FileName: String; Converter: String; rtbApp: TRichViewEdit;boole:Boolean): Boolean;

// Function to export RTF to a file.
//function ExportRTF(FileName: String; Converter: String; rtbApp: TRichViewEdit): Boolean;

// -----------------------------------------------------------------
// Functions to call if you want to know what can be converted
// -----------------------------------------------------------------

// Function to build a filter list, with available import and export converters.
function BuildFilterList(ForImport: Boolean): string;

// Function to build a list with available conveters.
function BuildConverterList(ForImport: Boolean; StrLst: TStringList): Boolean;

// -----------------------------------------------------------------
// Supportive functions - not to be called direct, unless you
// know what you are doing
// -----------------------------------------------------------------

// Initialize the selected converter.
function LoadConverter(Description: string; Import,boolExcel: boolean): HWND;

// Check if current file is of right format.
function IsKnownFormat(FileName: string): Boolean;

// Convert string to HGLOBAL.
function StringToHGLOBAL(const str: string): HGLOBAL;

// Procedure to free the converters.
procedure DoFreeConverters;

// Function to obtain the directory of WordPad. Not needed to be public, but maybe
// someone is looking for it.
function WordPadDir: string;

// Callback functions for reading and writing.
function Reading(CCH, nPercentComplete: integer): Integer; stdcall;
function Writing(flags, nPercentComplete: integer): Integer; stdcall;


implementation

type
// Our functions to convert the RTF-format to a foreign format, or a foreign format to the RTF-format.
// These functions are hidden in the converters.
RTF_CALLBACK = function(CCH, nPercentComplete: integer): Integer; stdcall;
TInitConverter = function(ParentWin: THandle; ParentAppName: LPCSTR): integer; stdcall;
TIsFormatCorrect = function(FileName, Desc: HGLOBAL): integer; stdcall;
TForeignToRtf = function(FileName: HGLOBAL; void: pointer{LPSTORAGE}; Buf, Desc, Subset: HGLOBAL; Callback: RTF_CALLBACK): integer; stdcall;
TRtfToForeign = function(FileName: HGLOBAL; void: pointer{LPSTORAGE}; Buf, Desc: HGLOBAL; Callback: RTF_CALLBACK): integer; stdcall;

var
CurrentConverter: HWND;
InitConverter: TInitConverter = nil;
IsFormatCorrect: TIsFormatCorrect = nil;
ForeignToRtf: TForeignToRtf = nil;
RtfToForeign: TRtfToForeign = nil;
hBuf: HGLOBAL;
bytesRead: integer = 0;
WritePos: integer = 0; // in Char, not WChar
WriteMax: integer = 0; // in Char, not WChar
RTFToWrite: string;
mstream: TMemorystream = nil;

const
nBufSize: integer = 4096;
MSTextConvKey = 'SOFTWARE/Microsoft/Shared Tools/Text Converters/';


function ImportAsRTF(FileName: String; Converter: String; rtbApp: TRichViewEdit;boole:Boolean): Boolean;
var
// Variables used for the actual conversion.
hSubset,
hFileName,
hDesc: HGLOBAL;
res: integer;
begin
Result := False; // We are very pessimistic.
try
if LoadConverter(Converter, True,boole) <> 0 then
begin
// Check selected file format.
if IsKnownFormat(FileName) then
begin
// prepare parameters
hSubset := StringToHGLOBAL('');
hDesc := StringToHGLOBAL('');

hFileName := StringToHGLOBAL(FileName);

hBuf := GlobalAlloc(GHND, nBufSize + 1);

try
Screen.Cursor := crHourGlass;

mstream := TMemoryStream.Create;
mstream.SetSize(512 * 1024); // initial: 512 kB, seems reasonable.

if Assigned(ForeignToRtf) then
res := ForeignToRtf(hFileName, nil, hBuf, hDesc, hSubset, Reading)
else
res := -1; // no valid entry point for DLL

if res = 0 then // Don't know any other states. Might be boolean.
begin
mstream.SetSize(mstream.Position); // shrink to right size
mstream.Position := 0;

//rtbApp.Lines.LoadFromStream(mStream);
//rtbApp.Clear;
//rtbApp.Format;
rtbApp.LoadRTFFromStream(mStream);
rtbApp.Format;
//rtbApp.WideLines.LoadFromStream(mStream);
mStream.Free;

Result := True;
end
else
Result := False;
finally
GlobalFree(hBuf);
GlobalFree(hFileName);
GlobalFree(hDesc);
GlobalFree(hSubset);
Screen.Cursor := crDefault;
end;
end
else
begin
ShowMessage('Not the correct file format');
Result := False;
end;
end;
except
Result := False;
end;
end;


{function ExportRTF(FileName: String; Converter: String; rtbApp: TRichViewEdit): Boolean;
var
hSubset,
hFileName,
hDesc: HGLOBAL;
res: integer;
iSelStart, iSelLength: Integer;
begin
if LoadConverter(Converter, False) <> 0 then
begin
if not (Assigned(InitConverter)
and LongBool(InitConverter(Application.Handle, PChar(Uppercase(Application.ExeName))))) then
begin
ShowMessage('Please report: InitConverter failed');
Result := False;
Exit;
end;

hSubset := StringToHGLOBAL('');
hDesc := StringToHGLOBAL('');
hFileName := StringToHGLOBAL(FileName);
hBuf := GlobalAlloc(GHND, nBufSize + 1);

try
Screen.Cursor := crHourGlass;
WritePos := 0;

if Assigned(RtfToForeign) then
begin
iSelStart := rtbApp.SelStart;
iSelLength := rtbApp.SelLength;

rtbApp.SelectAll; // This is done quick-and-dirty, but at the moment it works.

RTFToWrite := rtbApp.SelText;

rtbApp.SelStart := iSelStart;
rtbApp.SelLength := iSelLength;

WriteMax := length(RTFToWrite);

res := RtfToForeign(hFileName, nil, hBuf, hDesc, Writing);

RTFToWrite := '';

if res = 0 then
Result := True
else
Result := False;
end
else
begin
ShowMessage('Coult not export document');
Result := False;
end;

finally
GlobalFree(hBuf);
GlobalFree(hFileName);
GlobalFree(hDesc);
GlobalFree(hSubset);
Screen.Cursor := crDefault;
end;
end
else
Result := False;
end; }


// Try to obtain the WordPad directory.
function WordPadDir: string;
var
reg: TRegistry;
begin
reg := TRegistry.Create;

with reg do
try
RootKey := HKEY_LOCAL_MACHINE;

Result := '';

if OpenKey('/SOFTWARE/Microsoft/Windows/CurrentVersion/App Paths/WORDPAD.EXE', False) then
Result := ReadString('');

Result := ExtractFilePath(Result); // leaves the trailing backslash intact
finally
Free;
end;
end;


// The function "BuildFilterList" creates a string, that we can use as a filterlist
// in the dialog.
function BuildFilterList(ForImport: Boolean): string;
const
saImEx: array[False..True] of string = ('Export', 'Import');
var
regTxtConv: TRegistry;
regConvEntry: TRegistry;
slEntries: TStringList;
x,
i: integer;
extensions: string;
begin
regTxtConv := TRegistry.Create;
regConvEntry := TRegistry.Create;
slEntries := TStringList.Create;
Result := '';

with regTxtConv do
try
RootKey := HKEY_LOCAL_MACHINE;
if OpenKey(MSTextConvKey + saImEx[ForImport], False) then
GetKeyNames(slEntries);
finally
CloseKey;
Free;
end;

regConvEntry.RootKey := HKEY_LOCAL_MACHINE;
try
for i := 0 to slEntries.Count-1 do
begin
if regConvEntry.OpenKey(MSTextConvKey + saImEx[ForImport] + '/' + slEntries, false) then
try
extensions := '*.' + regConvEntry.ReadString('Extensions');
x := pos(' ', extensions);
while x > 0 do
begin
delete(extensions, x, 1);
insert(';*.', extensions, x);
x := pos(' ', extensions);
end;
Result := Result + regConvEntry.ReadString('Name') + '|' + extensions + '|';
except
// catch a faulty key mismatch
end;
regConvEntry.CloseKey;
end;
finally
regConvEntry.Free;
slEntries.Free;
end;

// We can always im/export RTF, but there is no (trivial) converter for,
// but we do want to show it...
Result := 'Rich Text Format|*.rtf|' + Result;

// Since the WordPad converters are identically to the Office converters,
// we test if WordPad is installed and if so, if we did find Word and/or
// Write format. If not, add them.
// NB: these are valid for both im- and export.
if WordPadDir <> '' then
begin
if (pos('Windows Write', Result) = 0) and
(FileExists(WordPadDir + 'write32.wpc')) then
Result := 'Windows Write|*.wri|' + Result;
if FileExists(WordPadDir + 'mswd6_32.wpc') then // do we have W6 converter?
if (pos('Word 6.0/95', Result) = 0) then
// no office converter for W6, add Wordpad as default converter
Result := 'Word 6.0/95|*.doc|' + Result
else
// Since Office converter seems buggy, add Wordpad converter as default
Result := 'Word 95 via WordPad|*.doc|' + Result;
end;

if (Result <> '') and (Result[Length(Result)] = '|') then
Delete(Result, Length(Result), 1); // strip trailing |
end;


// The function "BuildConverterList" creates a stringlist, in which all available
// converters are stored.
function BuildConverterList(ForImport: Boolean; StrLst: TStringList): Boolean;
const
saImEx: array[False..True] of string = ('Export', 'Import');
var
regTxtConv: TRegistry;
regConvEntry: TRegistry;
slEntries: TStringList;
i: integer;
begin
if not Assigned(StrLst) then
begin
Result := False;
Exit; // StrLst must be initialized.
end;

regTxtConv := TRegistry.Create;
regConvEntry := TRegistry.Create;
slEntries := TStringList.Create;

try
with regTxtConv do
try
RootKey := HKEY_LOCAL_MACHINE;
if OpenKey(MSTextConvKey + saImEx[ForImport], False) then
GetKeyNames(slEntries);
finally
CloseKey;
Free;
end;

regConvEntry.RootKey := HKEY_LOCAL_MACHINE;

try
for i := 0 to slEntries.Count-1 do
begin
if regConvEntry.OpenKey(MSTextConvKey + saImEx[ForImport] + '/' + slEntries, False) then
try
StrLst.Add(regConvEntry.ReadString('Name'));
except
// catch a faulty key mismatch
end;
regConvEntry.CloseKey;
end;
finally
regConvEntry.Free;
slEntries.Free;
end;

// We can always im/export RTF, but there is no (trivial) converter for,
// but we do want to show it...
StrLst.Insert(0, 'Rich Text Format');

// Since the WordPad converters are identically to the Office converters,
// we test if WordPad is installed and if so, if we did find Word and/or
// Write format. If not, add them.
// NB: these are valid for both im- and export.
if WordPadDir <> '' then
begin
if (pos('Windows Write', StrLst.Text) = 0) and
(FileExists(WordPadDir + 'write32.wpc')) then
StrLst.Insert(0, 'Windows Write');
if FileExists(WordPadDir + 'mswd6_32.wpc') then // do we have W6 converter?
if (pos('Word 6.0/95', StrLst.Text) = 0) then
// no office converter for W6, add Wordpad as default converter
StrLst.Insert(0, 'Word 6.0/95')
else
// Since Office converter seems buggy, add Wordpad converter as default
StrLst.Insert(0, 'Word 95 via WordPad');
end;

Result := True;
except
Result := False;
end;
end;


// The function "LoadConverter" loads a specific converter.
// We set the converter-functions as well.
function LoadConverter(Description: string; Import,boolExcel: boolean): HWND;
const
saImEx: array[false..true] of string = ('Export', 'Import');
var
regTxtConv: TRegistry;
regConvEntry: TRegistry;
slEntries: TStringList;
i: integer;
ConverterDLL: string;
begin
//regTxtConv := TRegistry.Create;
//regConvEntry := TRegistry.Create;

//slEntries := TStringList.Create;

Result := 0;
ConverterDLL := '';

{with regTxtConv do
try
RootKey := HKEY_LOCAL_MACHINE;
if OpenKey(MSTextConvKey + saImEx[Import], false) then
GetKeyNames(slEntries);
finally
CloseKey;
Free;
end;

regConvEntry.RootKey := HKEY_LOCAL_MACHINE;

try
for i := 0 to slEntries.Count - 1 do
begin
regConvEntry.OpenKey(MSTextConvKey + saImEx[Import] + '/' + slEntries, False);
try
if regConvEntry.ReadString('Name') = Description then // we've found our dll
ConverterDLL := regConvEntry.ReadString('Path'); // get dll-location & name
except
// catch a faulty key mismatch to be able to continue
end;
regConvEntry.CloseKey;
end;
finally
regConvEntry.Free;
slEntries.Free;
end; }

{if ConverterDLL = '' then // It could be a Wordpad provided converter
begin
if pos('Word 6.0/95', Description) > 0 then
ConverterDLL := WordPadDir + 'mswd6_32.wpc'
else if pos('Windows Write', Description) > 0 then
ConverterDLL := WordPadDir + 'write32.wpc'
else if pos('WordPad', Description) > 0 then
ConverterDLL := WordPadDir + 'mswd6_32.wpc';
end;}

if Import then begin
if not boolExcel then
ConverterDLL := ExtractFilePath(Application.ExeName)+'textconv/Mswrd832.cnv'
else
ConverterDLL := ExtractFilePath(Application.ExeName)+'textconv/Excel32.cnv';
end;
//else
// ConverterDLL := ExtractFilePath(Application.ExeName)+'textconv/WNWRD232.CNV'
if ConverterDLL <> '' then
begin
if CurrentConverter <> 0 then // Unload the current loaded converter.
FreeLibrary(CurrentConverter);

Result := LoadLibrary(PChar(ConverterDLL)); // Load the new converter.

if Result <> 0 then
begin
CurrentConverter := Result; // Try to initialize our functions.
@InitConverter := GetProcAddress(Result, 'InitConverter32');
@IsFormatCorrect := GetProcAddress(Result, 'IsFormatCorrect32');
@ForeignToRtf := GetProcAddress(Result, 'ForeignToRtf32');
@RtfToForeign := GetProcAddress(Result, 'RtfToForeign32');
end;
end;

if Result = 0 then
begin // On failure, reset...
@InitConverter := nil;
@IsFormatCorrect := nil;
@ForeignToRtf := nil;
@RtfToForeign := nil;
end;
end;


// The function "StringToHGlobal" converts a string in HGLOBAL.
function StringToHGLOBAL(const str: string): HGLOBAL;
var
new: PChar;
begin
Result := GlobalAlloc(GHND, Length(str) * 2 + 1);

new := GlobalLock(Result);

if new <> nil then
strcopy(new, PChar(str));

GlobalUnlock(Result);
end;


// The function "IsKnownFormat" is used to check if a selected file
// matches a converter-type.
function IsKnownFormat(FileName: string): Boolean;
var
hFileName,
hDesc: HGLOBAL;
begin
Result := False;

if not (Assigned(InitConverter)
and LongBool(InitConverter(Application.Handle, PChar(Uppercase(Application.ExeName))))) then
ShowMessage('Please report: InitConverter failed') // Question only is: report to who?
else
begin
hFileName := StringToHGLOBAL(FileName);
hDesc := StringToHGLOBAL('');
try
if Assigned(IsFormatCorrect) then
Result := LongBool(IsFormatCorrect(hFileName, hDesc)); // hDesc gets like 'MSWord6'
finally
GlobalFree(hDesc);
GlobalFree(hFileName);
end;
end;
end;


// The function "Reading" is used by the converter-DLL's.
// It is used to import a foreign format to the RTF-format.
function Reading(CCH, nPercentComplete: integer): Integer; stdcall;
var
tempBuf: PChar;
begin
tempBuf := GlobalLock(hBuf);

if CCH > 0 then
begin
if mstream.Position + CCH >= mstream.Size then // enlarge stream
mstream.SetSize(mstream.size + (mstream.size div 4)); // by .25
mstream.Write(tempBuf^, CCH);
end;

GlobalUnlock(hBuf);

inc(BytesRead, CCH);

Result := 0; // everything OK
end;


// The function "Writing" is used by the converter-DLL's.
// It is used to export the RTF-format to a foreign format.
function Writing(flags, nPercentComplete: integer): Integer; stdcall;
var
tempBuf: PChar;
begin
tempBuf := GlobalLock(hBuf);

if tempBuf = nil then
begin
Result := -8; // out of memory?
Exit;
end;

if writePos < writeMax then
begin
if (writeMax - writePos) < nBufSize then
bytesRead := writeMax - writePos
else
bytesRead := nBufSize;

move(RTFToWrite[WritePos+1], tempBuf^, bytesRead);

inc(writePos, bytesRead);
end
else
bytesRead := 0;

GlobalUnlock(hBuf);
Result := bytesRead;
end;


procedure DoFreeConverters;
begin
if CurrentConverter <> 0 then
begin
FreeLibrary(CurrentConverter);
CurrentConverter := 0;
end;
end;

initialization

finalization
DoFreeConverters;

end.
其中 导出的函数不好使 我给屏蔽了 我只使用了Word和Excel两个
================================================================================
不知那位能够帮助解决RTF->DOC问题
 
后退
顶部