Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 如何从数据库中获取Excel文件(BLOB)并对其执行读/写操作?_Database_Excel_Delphi - Fatal编程技术网

Database 如何从数据库中获取Excel文件(BLOB)并对其执行读/写操作?

Database 如何从数据库中获取Excel文件(BLOB)并对其执行读/写操作?,database,excel,delphi,Database,Excel,Delphi,我正在开发应用程序,需要读取和修改Excel文件中的一些数据 现在我是在本地做的,它可以工作,但问题是Excel文件需要在服务器上。 我使用TMemoryStream对第一个LoadFromFile和下一个LoadFromStream对数据集进行了如下操作: fileStream := TMemoryStream.Create; fileStream.LoadFromFile(sFileName); cdsExcel.LoadFromStream(fileStream); 文件名在哪里 基于T

我正在开发应用程序,需要读取和修改Excel文件中的一些数据

现在我是在本地做的,它可以工作,但问题是Excel文件需要在服务器上。 我使用
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