大富翁的高手们,救救小弟吧,小弟在这有礼了!...vba难题(在线等待) ( 积分: 200 )

  • 主题发起人 主题发起人 zhang214
  • 开始时间 开始时间
Z

zhang214

Unregistered / Unconfirmed
GUEST, unregistred user!
如何将指定的word单元格内容(图文混排)保存到数据库(批量),我已经搜遍了大富翁也没有找到合适的东西,请大富翁的高手多多指教
我的问题是这个样子的
我是在做一个毕业设计,里边涉及到试题的批量录入,我想以word的单元格为基础,让人
在单元格里录入试题,等录入完成了,在导入到数据库中,我的思路是这样的,先把单元格复制到剪贴板,然后再用剪切板操作把其写入到流中,最后把流写入到数据库(不用Rtf格式)。
但是问题就出在我在大富翁以前的留言中搜索出来剪切板操作的代码,能将单元格保存到bold字段,但是读出显示会有问题(代码如下),请各位高手指教.
Email为zhangzhiyuan303@sohu.com!

 
如何将指定的word单元格内容(图文混排)保存到数据库(批量),我已经搜遍了大富翁也没有找到合适的东西,请大富翁的高手多多指教
我的问题是这个样子的
我是在做一个毕业设计,里边涉及到试题的批量录入,我想以word的单元格为基础,让人
在单元格里录入试题,等录入完成了,在导入到数据库中,我的思路是这样的,先把单元格复制到剪贴板,然后再用剪切板操作把其写入到流中,最后把流写入到数据库(不用Rtf格式)。
但是问题就出在我在大富翁以前的留言中搜索出来剪切板操作的代码,能将单元格保存到bold字段,但是读出显示会有问题(代码如下),请各位高手指教.
Email为zhangzhiyuan303@sohu.com!

 
相关代码
procedure TFm1Main.Button1Click(Sender: TObject);/////这是存入过程
var ms: TMemoryStream;
var t1: OleVariant;
begin
t1:=WordControl.WordDocument.Tables.Item(1);
t1.cell(2,1).range.copy;
try
ms := TMemoryStream.Create;
SaveClipboard(ms);
qTopic.Append;
TBlobField(qTopic.FieldByName('content')).LoadFromStream(Ms);
qTopic.Post;
finally
ms.Free;
end; { Finally}

end;
procedure TFm1Main.Button2Click(Sender: TObject); //读出过程
var MemStream : TMemoryStream;
var t1: OleVariant;
begin
screen.Cursor:=crHourGlass;
Qtopic.close;
Qtopic.SQL.Clear;
Qtopic.SQL.Add('select * from tbTopic where id='+edit1.Text+'');
Qtopic.Open;
//Clipboard.Open;
//Clipboard.Clear;
try
MemStream := TMemoryStream.Create;
MemStream.Clear;
TBlobField(Qtopic.FieldByName('Content')).SaveToStream(MemStream);
MemStream.Position := 0;
LoadClipboard(MemStream);
t1:=WordControl.WordDocument.Tables.Item(1);
t1.cell(4,1).range.Paste;
finally
MemStream.Free;
end;
// Clipboard.Close;
screen.Cursor:=crDefault;
end;

procedure TFm1Main.LoadClipboard(S: TStream);
var
reader: TReader;
begin
Assert(Assigned(S));

reader := TReader.Create(S, 4096);
try
Clipboard.Open;
try
clipboard.Clear;
reader.ReadListBegin;
while not reader.EndOfList do //
begin
// showmessage(inttostr(reader.Position));
LoadClipboardFormat(reader);
end;
reader.ReadListEnd;
finally
Clipboard.Close;
end; { Finally }
finally
reader.Free
end; { Finally }
end; { LoadClipboard }
procedure TFm1Main.SaveClipboard(S:TStream);
var
writer: TWriter;
i: integer;
begin
Assert(Assigned(S));
writer := TWriter.Create(S, 4096);
try
Clipboard.Open;
try
writer.WriteListBegin;
for i := 0 to Clipboard.formatcount - 2 do
begin
//showmessage(inttostr( ClipBoard.Formats));
SaveClipboardFormat(Clipboard.Formats, writer);
end;
writer.WriteListEnd; //可以删除
finally
Clipboard.Close;
end; { Finally }
finally
writer.Free
end; { Finally }
end; { SaveClipboard }
procedure TFm1Main.CopyStreamToClipboard(fmt: cardinal; S: TStream);
var
hMem: THandle;
pMem: Pointer;
begin
Assert(Assigned(S));
S.Position := 0;
hMem := GlobalAlloc(GHND or GMEM_DDESHARE, S.Size);
if hMem <> 0 then
begin
pMem := GlobalLock(hMem);
if pMem <> nil then
begin
try
S.Read(pMem^, S.Size);
S.Position := 0;
finally
GlobalUnlock(hMem);
end;
Clipboard.Open;
try
Clipboard.SetAsHandle(fmt, hMem);
finally
Clipboard.Close;
end;
end { If }
else
begin
GlobalFree(hMem);
OutOfMemoryError;
end;
end { If }
else
OutOfMemoryError;
end; {CopyStreamToClipboard}

procedure TFm1Main.CopyStreamFromClipboard(fmt: cardinal; S: TStream);
Var hMem: THandle;
pMem: Pointer;
Begin

hMem := Clipboard.GetAsHandle(fmt );
If hMem <> 0 Then
Begin
pMem := GlobalLock( hMem );
If pMem <> Nil Then
Begin
S.Write( pMem^, GlobalSize( hMem ));
S.Position := 0;
GlobalUnlock( hMem );
End { If }
Else
raise Exception.Create(
'CopyStreamFromClipboard: could not lock global handle '+
'obtained from clipboard!');
End; { If }

end; { CopyStreamFromClipboard }
procedure TFm1Main.LoadClipboardFormat(reader: TReader);
var
fmt: integer;
fmtname: string;
size: integer;
ms: TMemoryStream;
begin
Assert(Assigned(reader));
fmt := reader.ReadInteger;
fmtname := reader.ReadString;
size := reader.ReadInteger;
ms := TmemoryStream.Create;
try
ms.Size := size;
reader.Read(ms.memory^, size);
if Length(fmtname) > 0 then
fmt := RegisterCLipboardFormat(PChar(fmtname));
if fmt <> 0 then
CopyStreamToClipboard(fmt, ms);
finally
ms.Free;
end; { Finally }
end; { LoadClipboardFormat }
procedure TFm1Main.SaveClipboardFormat(fmt: word; writer: TWriter);
var
fmtname: array[0..128] of char;
ms: TMemoryStream;
begin
Assert(Assigned(writer));
if 0 = GetClipboardFormatName(fmt, fmtname, sizeof(fmtname)) then
fmtname[0] := #0;
ms := TMemoryStream.Create;
try
CopyStreamFromClipboard(fmt, ms);
if ms.Size > 0 then
begin
writer.WriteInteger(fmt);
writer.WriteString(fmtname);
writer.WriteInteger(ms.Size);
writer.Write(ms.Memory^, ms.Size);
end; { If }
finally
ms.Free
end; { Finally }
end; { SaveClipboardFormat }



 
VBA,还是应该用VB来做,方便啊,提前先
 
to:renyi
谢谢您的参与,因为项目的大部分代码使用delphi,这块也希望用delphi写,如果有类似经验的话还望多多指教!先谢了!
 
在vb里打开word有单独控制word单元格的函数,不过效果不好,最好将word直接倒入access或者excel再进行努力,access或者excel会替你处理单元格的
 
那么长的代码,我看没人会帮你看的。
给你点建议,先分析出你出问题的地方,然后再把有问题的代码贴出来。另外呢,你光说会有问题,可是什么问题呢?你都不说叫人怎么帮你诊断?
这就像去医院看病一样,你应该哪里痛看哪里,总不会到医院去就叫医生把你全身检查一遍吧。然后你应该告诉医生你怎么个痛法,不然光说会痛,难道要医生把所有止痛片都开给你?
另外呢,DELPHI写VBA,我也写过一些,个人认为还好,应该不会比VB差到哪。
 
to:冰封
谢谢你的建议,我把我认为有问题的代码贴出来了!请指教!以前网上找来的是Clipboard.formatcount - 1,我用的时候会报错,我给成‘-2’就不报错了,但是我试了一下只有图片格式的东西会出问题,别的格式的显示都没有问题的(word中的艺术字和自选图形),希望能够帮忙!如果需要我可以给你代码,帮我调试一下!谢谢!
procedure TFm1Main.SaveClipboard(S:TStream);
var
writer: TWriter;
i: integer;
begin
Assert(Assigned(S));
writer := TWriter.Create(S, 4096);
try
Clipboard.Open;
try
writer.WriteListBegin;
for i := 0 to Clipboard.formatcount - 2 do //-1
begin
showmessage(inttostr( Clipboard.formatcount));
SaveClipboardFormat(Clipboard.Formats, writer);
end;
writer.WriteListEnd; //可以删除 //这个东西以前有的
finally
Clipboard.Close;
end; { Finally }
finally
writer.Free
end; { Finally }
end; { SaveClipboard }
 
可以这样试试:
1.复制word文档中整个表格到TXT档案中,这时表格会自动去掉,而内容会
有规律的排放;
2.直接把TXT档的内容岛入数据库(就如同导EXCEL差不多,具体见以前的帖子,
很详细的).
 
你没必要遍历每个格式,都存入流中,不浪费么!
WORD在剪贴板中会提供RFT格式的剪贴板格式,具体的格式的值,我以前做一个剪贴板查看器看过。现在记不清了。
你只要使用WORD的剪贴命令,然后使用这种格式粘贴到你的程序中就可以了。

你的问题估计是因为在流中碰到了结束字符,所以出现问题。这种问题好出现在剪贴板操作中,我就碰到过。RTF格式是文本格式,所以就不用担心读取时会出错。
 
to:wk_knife
您说的rtf格式我是知道的,但是现在的问题是:用rtf格式的文件,录入的内容和格式都会有不同程度的失真,上次版本用的是rtf格式,不太理想,所以这次想弄成完全word格式的,希望您给帮忙把上边的代码调试一下,或者给点思路谢谢,如果可能的话我的话题可以多给分!谢谢!
 
To:missinwind
复制word文档中整个表格到TXT档案中,这时表格会自动去掉,同时别的内容也会有不同程度的丢失,而我希望得到的是完全的word格式,没有任何内容的丢失,好像只能用自己操作剪切板,但是。。。。欢迎大家继续讨论,谢谢!
 
楼主你好:
我也在建立一个大型的题库。我是把纯粹的文字题目,及题目和答案中都没有图片等这些对象的题目全部写在文本文件中,然后从文本文件中读取入库,有图片等对象的放在WORD中备注,然后重新建立表,写到bold字段,我的题目主要有选择题,单,多选,案例分析这三种,想看看你的表和程序设计思路,交流一下!
 
To:tianrei
我的程序思路是这样的!
我的题目也是跟你的差不多,选择,填空以及问答题, 我想用vba控制word,生成相应的试题录入界面,让录入人员在word环境下录入试题(以单元格为单位),然后将这些内容,添加到数据库中!由于其中的试题内容字段,和试题答案字段是比较复杂的(可能会包括图文混排),所以用bold字段存取,我的问题就出在,将word的单元格通过剪切板保存到
流中,然后再把流存入bold字段,结果读出bold字段时,以前单元格中的图片无法显示,别的如文字,自选图形等格式的数据显示都比较正常!欢迎多多交流!
 
>>用rtf格式的文件,录入的内容和格式都会有不同程度的失真
不是让你用RTF格式的文件。而是WORD文档被复制到内存后,提供多种剪贴板格式,其中一种是RTF格式的。把这种格式的文本存起来就行了。

看了一下
if 0 = GetClipboardFormatName(fmt, fmtname, sizeof(fmtname)) then
fmtname[0] := #0; //这里设置为#0很不好,用TStream和TWrite很容易出问题。
fmtname是否可以不要? 因为已经有fmt了。

按理说保存数据的时候做了个for循环,把剪贴板中所有存在的格式都保存了一下,读出时用的是看TREADER到不到结束位置的方法的while循环,看的累啊。另外你的函数的命名最好改一下,宁可更长一些,看的头大。

再一个你的代码还可以精简一下:象
Clipboard.Open;
try
Clipboard.SetAsHandle(fmt, hMem);
finally
Clipboard.Close;
end;
只要Clipboard.SetAsHandle(fmt, hMem);就可以了。其他几句都是多余的。
而且这几句的问题好象不小。抛开多余的几句不说(问题一样)
Clipboard.SetAsHandle(fmt, hMem);本身会每次清空剪贴板,也就是说你读到剪贴板中的数据其实只有最后一种!
在这里不能用TCLIPBOARD,要用API才行。要同时存入多种格式到剪贴板,只要在打开,清空剪贴板后,反复调用SetClipboardData就可以了


 
To:wk_knife
谢谢您用心给我看问题,听了您的这些话,我似乎明白了一些东西,等我看看Api的东西,好好琢磨一下剪切板,有问题的话在向您请教!先谢了!前辈!
 
对了wk_knife前辈,关于剪切板的操作或者原理方面的东西,该看看那方面的书,或者您可以给我推荐一些资料!

 
The Tomes of Delphi Win32 Core API Windows 2000 Edition
Wordware The Tomes of Delphi Win32 Shell API Windows 2000 Edition
新编Windows API大全

搜一下,网上应该都有
 
to zhang214:
前两天比较忙,没空来这。
如果需要我帮你调试请发一份到doremifa@vip.sina.com。
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部