在网上看见一些关于将内存中的表存为EXCEL格式的磁盘文件(http://www.xker.com/article/articleview/2005-6-17/article_view_2010.htm),的确可行;
然后我反过来用同样的方法,将刚才用流写的EXCEL磁盘文件读入内存表,也成功了;那么,使用流是否可以任意读取EXCEL文件吗?我用该方法读取人家手工写的EXCEL文件,却失败了。
问:使用流可以读取EXCEL文件的内容吗?(EXCEL是简单的数据表,没有复杂的数据比如计算公式和宏等)。
下面贴出我的代码:

var
  Form1: TForm1;
  arXlsBegin: array[0..5] of Word = ($809, 8, 0, $10, 0, 0);
  arXlsEnd: array[0..1] of Word = ($0A, 00);
  arXlsString: array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
  arXlsNumber: array[0..4] of Word = ($203, 14, 0, 0, 0);
  arXlsInteger: array[0..4] of Word = ($27E, 10, 0, 0, 0);
  arXlsBlank: array[0..4] of Word = ($201, 6, 0, 0, $17);

//1、写为EXCEL文件
Procedure WriteExcelFile(FileName: string; bWriteTitle: Boolean; aDataSet: TDataSet);
var
  i, j: integer;
  Col, row: word;
  ABookMark: TBookMark;
  aFileStream: TFileStream;
procedure incColRow; //增加行列号
begin
  if Col = ADataSet.FieldCount - 1 then
  begin
    Inc(Row);
    Col :=0;
  end
  else
    Inc(Col);
end;procedure WriteStringCell(AValue: string);//写字符串数据
var
  L: Word;
begin
  L := Length(AValue);
  arXlsString[1] := 8 + L;
  arXlsString[2] := Row;
  arXlsString[3] := Col;
  arXlsString[5] := L;
  aFileStream.WriteBuffer(arXlsString, SizeOf(arXlsString));
  aFileStream.WriteBuffer(Pointer(AValue)^, L);
  IncColRow;
end;procedure WriteIntegerCell(AValue: integer);//写整数
var
  V: Integer;
begin
  arXlsInteger[2] := Row;
  arXlsInteger[3] := Col;
  aFileStream.WriteBuffer(arXlsInteger, SizeOf(arXlsInteger));
  V := (AValue shl 2) or 2;
  aFileStream.WriteBuffer(V, 4);
  IncColRow;
end;procedure WriteFloatCell(AValue: double);//写浮点数
begin
  arXlsNumber[2] := Row;
  arXlsNumber[3] := Col;
  aFileStream.WriteBuffer(arXlsNumber, SizeOf(arXlsNumber));
  aFileStream.WriteBuffer(AValue, 8);
  IncColRow;
end;begin
  if FileExists(FileName) then
    DeleteFile(FileName); //文件存在,先删除
  aFileStream := TFileStream.Create(FileName, fmCreate);
  try
    //写文件头
    aFileStream.WriteBuffer(arXlsBegin, SizeOf(arXlsBegin));
    //写列头
    Col := 0; Row := 0;
    if bWriteTitle then
      for i := 0 to aDataSet.FieldCount - 1 do
        WriteStringCell(aDataSet.Fields[i].FieldName);
      //写数据集中的数据
    aDataSet.DisableControls;
    ABookMark := aDataSet.GetBook;
    aDataSet.First;
    while not aDataSet.Eof do
    begin
      for i := 0 to aDataSet.FieldCount - 1 do
      case ADataSet.Fields[i].DataType of
      ftSmallint, ftInteger, ftWord, ftAutoInc, ftBytes:
        WriteIntegerCell(aDataSet.Fields[i].AsInteger);
      ftFloat, ftCurrency, ftBCD:
        WriteFloatCell(aDataSet.Fields[i].AsFloat)
      else
        WriteStringCell(aDataSet.Fields[i].AsString);
      end;
      aDataSet.Next;
    end;
     //写文件尾
    AFileStream.WriteBuffer(arXlsEnd, SizeOf(arXlsEnd));
    if ADataSet.BookValid(ABookMark) then aDataSet.GotoBook(ABookMark);
  Finally
     AFileStream.Free;
     ADataSet.EnableControls;
  end;
end;
//2、测试读
Procedure ReadExcelFile(FileName: string);
var
  i, j: integer;
  Col, row: word;
  ABookMark: TBookMark;
  aFileStream: TFileStream;
  s: string[5];
begin
  aFileStream := TFileStream.Create(FileName, fmOpenRead);
  with aFileStream do
  try
    //读文件头
    ReadBuffer(arXlsBegin, SizeOf(arXlsBegin));
    //读列头
    Col := 0; Row := 0;
    ReadBuffer(arXlsString, SizeOf(arXlsString));
    setlength(s,5);
    aFileStream.ReadBuffer(s[1], 255);
    showmessage(s);  finally
    free;
  end;end;

解决方案 »

  1.   

    *******  导出到excel 
    EXEC master..xp_cmdshell ’bcp SettleDB.dbo.shanghu out c:\temp1.xls -c -q -S"GNETDATA/GNETDATA" -U"sa" -P""’ /***********  导入Excel 
    SELECT * 
    FROM OpenDataSource( ’Microsoft.Jet.OLEDB.4.0’, 
      ’Data Source="c:\test.xls";User ID=Admin;Password=;Extended properties=Excel 5.0’)...xactions 
    SELECT cast(cast(科目编号 as numeric(10,2)) as nvarchar(255))+’ ’ 转换后的别名 
    FROM OpenDataSource( ’Microsoft.Jet.OLEDB.4.0’, 
      ’Data Source="c:\test.xls";User ID=Admin;Password=;Extended properties=Excel 5.0’)...xactions /** 导入文本文件 
    EXEC master..xp_cmdshell ’bcp "dbname..tablename" in c:\DT.txt -c -Sservername -Usa -Ppassword’ /** 导出文本文件 
    EXEC master..xp_cmdshell ’bcp "dbname..tablename" out c:\DT.txt -c -Sservername -Usa -Ppassword’ 
    或 
    EXEC master..xp_cmdshell ’bcp "Select * from dbname..tablename" queryout c:\DT.txt -c -Sservername -Usa -Ppassword’ 导出到TXT文本,用逗号分开 
    exec master..xp_cmdshell ’bcp "库名..表名" out "d:\tt.txt" -c -t ,-U sa -P password’ 
    BULK INSERT 库名..表名 
    FROM ’c:\test.txt’ 
    WITH ( 
        FIELDTERMINATOR = ’;’, 
        ROWTERMINATOR = ’\n’ 

    --/* dBase IV文件 
    select * from 
    OPENROWSET(’MICROSOFT.JET.OLEDB.4.0’ 
    ,’dBase IV;HDR=NO;IMEX=2;DATABASE=C:\’,’select * from [客户资料4.dbf]’) 
    --*/ --/* dBase III文件 
    select * from 
    OPENROWSET(’MICROSOFT.JET.OLEDB.4.0’ 
    ,’dBase III;HDR=NO;IMEX=2;DATABASE=C:\’,’select * from [客户资料3.dbf]’) 
    --*/ --/* FoxPro 数据库 
    select * from openrowset(’MSDASQL’, 
    ’Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\’, 
    ’select * from [aa.DBF]’) 
    --*/ /**************导入DBF文件****************/ 
    select * from openrowset(’MSDASQL’, 
    ’Driver=Microsoft Visual FoxPro Driver; 
    SourceDB=e:\VFP98\data; 
    SourceType=DBF’, 
    ’select * from customer where country != "USA" order by country’) 
    go 
    /***************** 导出到DBF ***************/ 
    如果要导出数据到已经生成结构(即现存的)FOXPRO表中,可以直接用下面的SQL语句 insert into openrowset(’MSDASQL’, 
    ’Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\’, 
    ’select * from [aa.DBF]’) 
    select * from 表 说明: 
    SourceDB=c:\  指定foxpro表所在的文件夹 
    aa.DBF        指定foxpro表的文件名.  
    /*************导出到Access********************/ 
    insert into openrowset(’Microsoft.Jet.OLEDB.4.0’, 
       ’x:\A.mdb’;’admin’;’’,A表) select * from 数据库名..B表 /*************导入Access********************/ 
    insert into B表 selet * from openrowset(’Microsoft.Jet.OLEDB.4.0’, 
       ’x:\A.mdb’;’admin’;’’,A表) *********************  导入 xml 文件 DECLARE @idoc int 
    DECLARE @doc varchar(1000) 
    --sample XML document 
    SET @doc =’ 
    <root> 
      <Customer cid= "C1" name="Janine" city="Issaquah"> 
          <Order oid="O1" date="1/20/1996" amount="3.5" /> 
          <Order oid="O2" date="4/30/1997" amount="13.4">Customer was very satisfied 
          </Order> 
       </Customer> 
       <Customer cid="C2" name="Ursula" city="Oelde" > 
          <Order oid="O3" date="7/14/1999" amount="100" note="Wrap it blue 
                 white red"> 
                <Urgency>Important</Urgency> 
                Happy Customer. 
          </Order> 
          <Order oid="O4" date="1/20/1996" amount="10000"/> 
       </Customer> 
    </root> 
    ’ 
    -- Create an internal representation of the XML document. 
    EXEC sp_xml_preparedocument @idoc OUTPUT, @doc -- Execute a SELECT statement using OPENXML rowset provider. 
    SELECT * 
    FROM OPENXML (@idoc, ’/root/Customer/Order’, 1) 
          WITH (oid     char(5), 
                amount  float, 
                comment ntext ’text()’) 
    EXEC sp_xml_removedocument @idoc
      

  2.   

    maming2003(嘿!兄弟!!要煤不???) :*******  导出到excel 
    EXEC master..xp_cmdshell ’bcp SettleDB.dbo.shanghu out c:\temp1.xls -c -q -S"GNETDATA/GNETDATA" -U"sa" -P""’ 是SQLSQERVER上的数据吧,但是因为考虑版权问题,操作电脑上没安装OFFICE的任何软件,除了正版的WINDOWS操作系统外。还有没有其他将DATASET中的数据存为EXCEL的方法?
      

  3.   

    金山et服务器有很好的文档.
    http://www.codesky.net/club/index.asp?id=845