情况是这样的,我有一个软件提供了EXCEL模式的实时保存记录功能,我想用DELPHI做一个将EXCEL文档实时导入至MSSQL数据库的小软件,要求就是一旦发现EXCEL文档记录发生改变(例如增加了1条记录)就实时的将这条记录导入到MSSQL中,全程用TIMER自动导入,无需要工操作!EXCEL文档(CVS格式)是在不停增加记录的(其它软件自动产生的相关记录),我想设定一个TIMER时间间隔,写一段Excel to Mssql的语句,将新产生的数据从Excel导入到Mssql数据库中,要保证数据无重复导入的情况!那位仁兄可否源码参考一二。

解决方案 »

  1.   

    可以用ADO 连接Excel的方式 读取数据,再把ADOQuery读取到的数据写进MSSQl
      

  2.   

    思路是这样的,我也清楚!关键是循环读取和无重复性导入数据库中,最好能写个DEMO看下,谢谢了!
      

  3.   

    Excel to Mssql可以用dts实现,保存成dts包调用,自己搜一下对excel文件可以判断他的大小或最后修改日期。这个,具体代码自己google一下好了,我也是google,就不拷贝粘贴了
      

  4.   

    如果CSV文件的数据量很大,你的速度不是会越来越慢吗?
      

  5.   

    不知道你那个excel表能不能再加个字段,再加一个boolean字段,如果已经导入到数据库里的设为1,新增肯定就不是1了,那样你就只查字段不是1的,有了就往里导。
      

  6.   

    当数据量达到百万时,加载一个CSV文件也是很慢的,虽然有一个boolean字段,但判断起来也不容易吧!
      

  7.   

    谢谢大家!回四楼的兄弟,这个流程有可能我没讲清楚,我要保证数据没有重复性导入,用DTS是可以导入,也可以实现自动化,但不能保证数据唯一性,其实二楼的方法是我正在想办法解决的,这样吧,我把我正在写的源码给大家看下,大家看我应该如何修改!
    unit ExcelCounts;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, ComObj;type
      ExcelCount = class
      Index: Integer;
      private
          { Private declarations }
      public
      function FileIsNull(fName: String): Boolean;   //记录数是否为空
      function FileIsEdit(fName: String): Boolean;   //记录数是否被修改
      function IsFileCount(fName: String): integer;  //获取Excel记录行数
      procedure ExcelToSql(fName: String; TableName: String);    //将Excel记录导入MSSQL库    { Public declarations }
      end;implementationuses IsFile, udmUser;function ExcelCount.IsFileCount(fName: String): Integer;   //获取Excel记录行数
    var
      ExcelApp: Variant;
    begin
      ExcelApp := CreateOleObject( 'Excel.Application' );    //创建Excel实例
      ExcelApp.WorkBooks.Open( 'fName',0,False );  //打开已存在的工作簿
      ExcelApp.visible:=false;                  //不显示当前窗口
      ExcelApp.Worksheets[1].activate;    //设置第1个工作表为活动工作表
      Result := ExcelApp.WorkSheets[1].UsedRange.Rows.Count;    //得到excel的行数
    end;
    function ExcelCount.FileIsNull(fName: String): Boolean;
    var
      MaxCount: Integer;
    begin
      Result := False;
      MaxCount := IsFileCount(fName);
      if MaxCount = 0 then
      Result := False
      else
      Result := True;
    end;function ExcelCount.FileIsEdit(fName: String): Boolean;
    var
      MaxCount: Integer;
    begin
      Result := False;
      MaxCount := IsFileCount(fName);
      if MaxCount>Index then
      Result := True
      else
      Result := False;
      Index := MaxCount;
    end;procedure ExcelCount.ExcelToSql(fName: String; TableName: String);
    var
      excelx,excely : string;
      ExcelApp,WorkBook: Variant;
      ExcelRowCount: integer;
      i: integer;
    begin
      try
       ExcelApp := CreateOleObject('Excel.Application');
       WorkBook := ExcelApp.WorkBooks.Open(fName);//使用参数fName调用excel档路径
       ExcelApp.Visible := false;
       Index := 1;
       for i := Index to ExcelRowCount + 1 do
         begin
         Excelx := ExcelApp.Cells[i,1].Value;
         Excely := ExcelApp.Cells[i,2].Value;
           if ((excelapp.Cells[i,1].Value = '') and (ExcelApp.Cells[i,2].Value = '')) then
    //指定excel档的第 i 行 ,第 1,2(看情况而定)行如果为空就退出,这样的设定,最好是你的档案这两行对应数据库中不能为空的数据
             exit
           else
           with UserDM.adqTemp do
             begin
             Close;
             Sql.clear;
             sql.add(insert into TableName(name,address) values(:name,:address));
             parambyname('name').asstring := excelx;//excel档的第一列插入到TableName表的 name栏位;
             parambyname('address').asstring := excely;//excel档的第二列插入到TableName表的 address 栏位;
             execsql;
             end;
          end;
          finally
          WorkBook.Close;
          ExcelApp.Quit;
          ExcelApp := Unassigned;
          WorkBook := Unassigned;
          end;
    end;end.
      

  8.   

    思路是不是出问题了,既然你已经实现用EXCEL实时保存记录,为什么不在往EXCEL保存记录的同时,
    也往MSSQL写记录
      

  9.   

    回九楼的兄弟,是这样的,EXCEL实时保存不是我编程实现的,是另外软件实现的。
      

  10.   

    同时回一下5楼的兄弟的疑问,CVS是每天一生成,所以量不会很大,文件前缀是自行设定加上当天日期例如: TCPIP20080729.CVS 明天就是TCPIP20080730.CVS ,所以不用担心这个问题! 
      

  11.   


    /*
    --下边是sql语句的实现,写到你的程序里就可以了(注意标点符号)
    --data 是数据库表名
    --在查出excel表中数据后给sheet1$加个别名,如: A
    加入这句 where not exists(select 1 from data where id = A.id)
    */
    insert into data 
    select * from 
      OpenDataSource('Microsoft.Jet.OLEDB.4.0','Data Source="Data Source";Extended Properties="Excel 8.0;HDR=Yes;";Persist Security Info=False'')'...sheet1$ A
    where not exists(select 1 from data where id = A.id) 
      

  12.   

    CVS文件中的计录肯定是顺序增加的吧,每次insert完成之后计录一下当前已经插入到的计录数,下次再插入的时候可以从计录的已经插入数的下一行开始读取。如加一个配置文件或者写一个文本文件,用来计录当前读到的计录总数,然后在下次读的时候,先取一下这个值,在你的ExcelToSql中不是从index=1读取,而是从你读取的这个值+1开始,不知道可行否?
      

  13.   

    是的,楼上兄台的观念与我要求相符,具体实现不知如何编写,不知楼上仁兄能否写个DEMO指点小弟一下!
      

  14.   

    照14楼的把SQL改了就OK了啊