Database 如何从数据库中获取Excel文件(BLOB)并对其执行读/写操作?
我正在开发应用程序,需要读取和修改Excel文件中的一些数据 现在我是在本地做的,它可以工作,但问题是Excel文件需要在服务器上。 我使用Database 如何从数据库中获取Excel文件(BLOB)并对其执行读/写操作?,database,excel,delphi,Database,Excel,Delphi,我正在开发应用程序,需要读取和修改Excel文件中的一些数据 现在我是在本地做的,它可以工作,但问题是Excel文件需要在服务器上。 我使用TMemoryStream对第一个LoadFromFile和下一个LoadFromStream对数据集进行了如下操作: fileStream := TMemoryStream.Create; fileStream.LoadFromFile(sFileName); cdsExcel.LoadFromStream(fileStream); 文件名在哪里 基于T
TMemoryStream
对第一个LoadFromFile
和下一个LoadFromStream
对数据集进行了如下操作:
fileStream := TMemoryStream.Create;
fileStream.LoadFromFile(sFileName);
cdsExcel.LoadFromStream(fileStream);
文件名在哪里
基于TOpenDialog
抓取
目前,Excel文件在DB中,我正在寻找对其执行读/写操作的最佳方法
是否有机会从客户端数据集中读取Excel文件,或者我是否应该将其保存在本地,执行操作,然后再次将其发送到服务器?问题是,客户端根本不应该访问该文件
要打开Excel文件,我使用:
Wb := ExApp.Workbooks.Open(sFileName, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, LCID);
所以仍然需要原始文件名才能打开Excel文件
我真的很感谢你的帮助和想法。谢谢大家! 本例使用Delphi Tokyo 10.2.2、DBISAM作为数据库和Excel 2016。这将从数据库将Excel文件加载到
TOleContainer
中,您可以在其中进行修改,然后将Excel文件保存回数据库
我创建了一个名为TOleContainerFileIO
的类,其中完成了大部分工作。虽然本例使用DBISAM,TOleContainerFileIO
使用TDataset
,因此任何TDataset
子代都可以工作
下面是我的示例项目的主要表单代码
unit uMainForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, OleCtnrs, DB, uOleContainerFileIO, dbisamtb,
Vcl.Menus;
type
TForm1 = class(TForm)
tExcelDB: TDBISAMTable;
MainMenu1: TMainMenu;
File1: TMenuItem;
LoadWorksheetfromDB1: TMenuItem;
SaveWorksheettoDB1: TMenuItem;
OleContainer1: TOleContainer;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure LoadWorksheetfromDB1Click(Sender: TObject);
procedure SaveWorksheettoDB1Click(Sender: TObject);
private
fOleContainerFileIO: TOleContainerFileIO;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormShow(Sender: TObject);
begin
tExcelDB.open;
fOleContainerFileIO := TOleContainerFileIO.create(self, OleContainer1);
end;
// TMainmenu menuitem, File > LoadWorksheetFromDB
procedure TForm1.LoadWorksheetfromDB1Click(Sender: TObject);
begin
fOleContainerFileIO.LoadFileFromDB(tExcelDB, 'XLSFile');
end;
// TMainmenu Menuitem, File > Save WorksheetToDB
procedure TForm1.SaveWorksheettoDB1Click(Sender: TObject);
begin
fOleContainerFileIO.SaveFileToDb;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
fOleContainerFileIO.free;
end;
end.
这是TOleContainerFileIO
类
unit uOleContainerFileIO;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ShellAPi, ExtCtrls, OleCtnrs, DB, ComCtrls;
type
TOleContainerFileIO = class(TComponent)
private
fTempfilename: string;
fContainer: TOleContainer;
fDataset: TDataset;
fBlobFieldname: string;
function GetWindowsTempFolder: string;
public
constructor create(AOwner: TComponent; AContainer: TOleContainer); reintroduce;
function Active: Boolean;
procedure LoadFromFile(const AFilename: string);
procedure LoadFileFromDB(ADataset: TDataSet; const ABlobFieldname: string);
procedure SaveFileToDb;
end;
implementation
function TOleContainerFileIO.GetWindowsTempFolder: String;
var
tempFolder: array[0..MAX_PATH] of Char;
begin
GetTempPath(MAX_PATH, @tempFolder);
result := StrPas(tempFolder);
end;
constructor TOleContainerFileIO.create(AOwner: TComponent; AContainer: TOleContainer);
begin
inherited create(AOwner);
fContainer := AContainer;
end;
function TOleContainerFileIO.Active: boolean;
begin
result := ((fDataset.Active) and (fContainer <> nil));
end;
Procedure TOleContainerFileIO.LoadFromFile(const AFilename: string);
begin
fContainer.CreateObjectFromFile(AFilename, false);
fContainer.AutoActivate := aaManual;
fContainer.Iconic := false;
fContainer.CopyOnSave := false;
fContainer.DoVerb(ovShow);
fContainer.Run;
end;
procedure TOleContainerFileIO.LoadFileFromDB(ADataset: TDataSet; const ABlobFieldname: string);
var
fs: TFileStream;
bs: TStream;
begin
fDataset := ADataset;
fBlobFieldname := ABlobFieldname;
if fDataset.Active = False then
raise exception.Create('Load document from Database failed, Dataset is not active');
if fDataset.Fields.FindField(fBlobFieldname)= nil then
raise exception.Create('Load document from Database failed, '+fBlobFieldname+' not found');
bs := fDataset.CreateBlobStream(fDataset.FieldByName(fBlobFieldname), bmRead);
try
bs.seek(0, soFromBeginning);
// create temp file, could use guid.xls here instead of random..
fTempfilename := GetWindowsTempFolder+'Tempfile-'+inttostr(random(100000000))+'.xls';
fs := TFileStream.Create(fTempfilename, fmCreate);
try
fs.CopyFrom(bs, bs.size)
finally
fs.free;
end;
finally
bs.Free;
end;
fContainer.CreateObjectFromFile(fTempfilename, false);
try
fContainer.AutoActivate := aaManual;
fContainer.Iconic := False;
fContainer.CopyOnSave := false;
fContainer.DoVerb(ovShow);
fContainer.Run;
finally
Deletefile(fTempfilename);
end;
end;
procedure TOleContainerFileIO.SaveFileToDb;
var
fs: TFileStream;
bs: TStream;
begin
if fDataset.Active = False then
raise exception.Create('Load Excel from Database failed, Dataset is not active');
if fDataset.Fields.FindField(fBlobFieldname)= nil then
raise exception.Create('Save document to Database failed, '+fBlobFieldname+' does not found');
fContainer.OldStreamFormat := true;
fContainer.SaveAsDocument(fTempfilename);
fDataset.edit;
bs := fDataset.CreateBlobStream(fDataset.FieldByName(fBlobFieldname), bmWrite);
try
try
bs.seek(0, soFromBeginning);
fs := TFileStream.Create(fTempFilename, fmOpenRead, fmShareDenyNone);
try
try
bs.CopyFrom(fs, fs.size);
fDataset.Post;
finally
fs.free;
end;
finally
DeleteFile(fTempfilename);
end;
except
fDataset.Cancel;
raise;
end;
finally
bs.free;
end;
end;
end.
我正在用Tolecontainer做一个项目。。我从数据库中打开文件,加载到TOleContainer中,然后将文件保存回数据库,而用户不直接知道文件信息。如果这是你想要的,我可以发布一个答案。@johnesley:我认为这是值得发布的答案,即使这可能不是OP所期望的。我也一直在思考类似的问题,在试图找到任何可以从流中加载工作簿的内容时,我画了一张空白纸。@johnesley谢谢,听起来像是个主意。如果您能发布您的解决方案,我们将不胜感激。我正在努力找到最好的方法。@Martyna也谢谢你@Johnesley您能介绍一下您的解决方案吗?如何从数据库加载这个blob文件,打开它进行一些更改,然后将其保存回去?谢谢@我的朋友发了一个样品。谢谢你的回答!这很有帮助。还有一个问题。如何从容器中获取
fileName
?我需要使用Wb:=ExApp.Workbooks.open打开它(文件名,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,LCID)
在TOleContainer中打开文档后,您可以使用OleContainer.SaveAsDocument(filename)
将其保存到您选择的文件名。
object Form1: TForm1
Left = 554
Top = 153
Caption = 'Excel OleContainer Test'
ClientHeight = 606
ClientWidth = 885
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
Menu = MainMenu1
OldCreateOrder = False
OnClose = FormClose
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object OleContainer1: TOleContainer
Left = 0
Top = 0
Width = 885
Height = 606
Align = alClient
Caption = 'OleContainer1'
TabOrder = 0
ExplicitLeft = 8
ExplicitTop = 8
ExplicitWidth = 1073
ExplicitHeight = 772
end
object tExcelDB: TDBISAMTable
DatabaseName = 'C:\Users\amazo\Desktop\OleContainerTest'
EngineVersion = '4.44 Build 3'
TableName = 'ExcelDB'
Left = 64
Top = 96
end
object MainMenu1: TMainMenu
Left = 64
Top = 176
object File1: TMenuItem
Caption = 'File'
object LoadWorksheetfromDB1: TMenuItem
Caption = 'Load Worksheet from DB'
OnClick = LoadWorksheetfromDB1Click
end
object SaveWorksheettoDB1: TMenuItem
Caption = 'Save Worksheet to DB'
OnClick = SaveWorksheettoDB1Click
end
end
end
end