当前位置:首页
开发技术指南» 文章正文
    引言:
 

 

    摘要: 收集相关的计算机ftp资源,谢谢! ......
    摘要: 收集相关的计算机ftp资源,谢谢! ......


怎样实现excel和数据库的互相关联的问题

用户对excel的操作很熟悉,提出要把数据库的内容导出到excel,修改后可以再导回数据库,我觉的这种做法不是很好,但想不出一个好的理由来说服他们。请大家说说这样做有什么不好,有没有可能实现,谢谢

NO.1   作者: WnEunfn

可以实现的(实际上你可以参考SQLServer2000的"导入与导出数据"功能)  
  不过不建议你这么无条件地满足用户的要求。  
  在我看来,最主要的一点是,是数据的安全性、完整性问题:  
  由于数据直接从Excel->Database,所有的企业逻辑(特别是约束条件),只要不是在SQL   Server中建立了约束、Trigger的,都将无法实现。这将导致数据的安全问题。

NO.2   作者: bluemeteor

不要一切都遵照甲方的意图,以客户为中心是从客户的角度来长远思考,而不是一切都顺从他的思路,坚持自己的观点才能得到尊重和支持,才能成为一名合格的乙方

NO.3   作者: scu96124678

在C++Builder中用Ole控制Excel表  
  黑龙江省通信公司   姜宏华  
   
  利用C++Builder的快速报表做表格是比较麻烦的事儿。如果打出来的表格需要手工修改数据,或者要保存成可以编辑的文件,那怎么办?现在许多单位用的都是Excel表格,如何让程序做出来的报表和Excel兼容,也是问题。那么就可以让C++Builder直接操作Excel表,这样就方便多了。  
  笔者在实际工作中经常用Excel表做数据报表,大多数表格的数据都要从数据库中读取,这样我就用C++Builder做了一个报表程序,方便了很多,现在把它共享给C++Builder爱好者们,就算为丰富C++Builder的文档资料做点事情吧。  
  首先把Excel报表文件保存到一个指定目录下,最好放在可执行程序的子目录下,作为模板文件。可以把报表标题、表头等设置好。这里是保存在trpt子目录下。  
  然后建一个report目录,作为报表目标文件夹,存放填好数据的报表,可以由用户直接操作。  
  好,现在就来工作吧。  
  首先确定在你的机器中装有Office。这里一Office2000为例。  
  在C++Builder中新建一个工程,在窗体Form1上面放一个两个按钮SaveButton和ReadButton,分别用来保存数据到Excel表和显示刚刚保存的Excel表。  
  在SaveButton按钮的单击事件中把从数据库中取到的数据放入到指定的Excel表中并将改文件拷贝到report目录下。在ReadButto按钮的单击事件中显示report目录下的报表文件,方便用户修改和另外保存。  
  在Form1.h头文件中定义几个变量:  
  private:  
  Variant   Ex,Wb,Sheet,ERange,EBorders;  
  并在文件头中包含如下语句:  
  #include   "Excel_2K_SRVR.h"  
  #include   <OleServer.hpp>  
  在Form1.cpp的文件头中加入  
  #pragma   link   "Excel_2K_SRVR"  
  主要代码如下:  
  void   __fastcall   TForm1::   SaveButtonClick(TObject   *Sender)  
  {  
  try  
  {  
  SaveButton->Enabled   =   false;  
  ReadButton->Enabled   =   false;//使两个按钮无效  
   
  //取报表文件CardSend.xls的完整目录名  
  AnsiString   ExcelFileName   =   GetCurrentDir()+"\\trpt\\table.xls";    
   
  if(!FileExists(ExcelFileName))  
  {  
  Application->MessageBox("报表模板文件不存在,无法打开!",  
  "错误",MB_ICONSTOP|MB_OK);  
  return;  
  }  
  //建立Excel的Ole对象Ex  
  try  
  {  
  Ex   =   Variant::CreateObject("Excel.Application");  
  }  
  catch(...)  
  {  
  Application->MessageBox("无法启动Excel","错误",MB_ICONSTOP|MB_OK);  
  return;  
  }  
  //设置Excel为不可见  
  Ex.OlePropertySet("Visible",false);  
  //打开指定的Excel报表文件。报表文件中最好设定只有一个Sheet。  
  Ex.OlePropertyGet("WorkBooks").OleProcedure("Open",ExcelFileName.c_str());  
  Wb   =   Ex.OlePropertyGet("ActiveWorkBook");  
  Sheet   =   Wb.OlePropertyGet("ActiveSheet");//获得当前默认的Sheet  
   
  //清空Excel表,这里是用循环清空到第300行。对于一般的表格已经足够了。  
  AnsiString   strRowTemp;    
  AnsiString   strRange;  
  int   iCols,iRows;//记录列数和行数  
   
  /*从第三行开始,到第300行止。一般第一行是表标题,第二行是副标题或者制表日期。*/  
  for(iRows=3;iRows<300;iRows++)  
  {   //假设只有6列。  
  for   (iCols   =   1;iCols   <   7;   iCols++)  
  {  
  //清空行  
  Sheet.OlePropertyGet("Cells",iRows,iCols).OlePropertySet("Value","");  
  }  
  //去掉表格边框  
  strRange   =   "A"+IntToStr(iRows)+":F"+IntToStr(iRows);//获取操作范围  
  ERange   =   Sheet.OlePropertyGet("Range",strRange.c_str());  
  EBorders   =   ERange.OlePropertyGet("Borders");//获取边框对象  
  EBorders.OlePropertySet("linestyle",xlNone);  
  }  
   
  AnsiString   strPtrDate;   //存放当前日期,作为制表日期  
  DateSeparator   =   -;  
  ShortDateFormat   =   "yyyy/m/d";//设置为年/月/日格式  
   
  strPtrDate   =   DateToStr(Date());//取当前日期  
   
  AnsiString   strYear   =   strPtrDate.SubString(1,4);  
  strPtrDate   =   strPtrDate.SubString(6,strPtrDate.Length()-5);  
  AnsiString   strMonth   =   strPtrDate.SubString(1,strPtrDate.Pos("-")-1);  
  AnsiString   strDay   =    
  strPtrDate.SubString(strPtrDate.Pos("-")+1,  
  strPtrDate.Length()-strPtrDate.Pos("-"));  
  strPtrDate   =   strYear+"年"+strMonth+"月"+strDay+"日";  
   
  AnsiString   strData   =   "报表标题";//报表标题  
  //将报表标题置于第一行第一列。在此之前,应将报表文件的标题格式设定好。  
  Sheet.OlePropertyGet("Cells",1,1).OlePropertySet("Value",  
  strData.c_str());  
  //将制表日期置于表格第二行的右侧。  
  Sheet.OlePropertyGet("Cells",2,5).OlePropertySet("Value",  
  strPtrDate.c_str());  
   
  iRows   =   3;//在第三行放置表格的列名  
  Sheet.OlePropertyGet("Cells",iRows,1).OlePropertySet("Value","列名1");  
  Sheet.OlePropertyGet("Cells",iRows,2).OlePropertySet("Value","列名2");  
  Sheet.OlePropertyGet("Cells",iRows,3).OlePropertySet("Value","列名3");  
  Sheet.OlePropertyGet("Cells",iRows,4).OlePropertySet("Value","列名4");  
  Sheet.OlePropertyGet("Cells",iRows,5).OlePropertySet("Value","列名5");  
  Sheet.OlePropertyGet("Cells",iRows,6).OlePropertySet("Value","列名6");  
  //画表格边框,在A3:F3之间取范围  
  strRange   =   "A"+IntToStr(iRows)+":F"+IntToStr(iRows);  
  ERange   =   Sheet.OlePropertyGet("Range",strRange.c_str());  
  EBorders   =   ERange.OlePropertyGet("Borders");  
  EBorders.OlePropertySet("linestyle",xlContinuous);  
  EBorders.OlePropertySet("weight",xlThin);  
  EBorders.OlePropertySet("colorindex",xlAutomatic);  
  iRows++;  
  //从数据库中取数据(略),假设数据集放入Query1中。  
  Query1->Open();//打开数据集  
  //循环取数  
  while(!Query1->Eof)  
  {    
  //循环取字段的数据放到Excel表对应的行列中  
  for(iCols=1;iCols<7;iCols++)  
  {    
  strRowTemp   =   Query1->Fields->Fields[iCols-1]->AsString;  
  Sheet.OlePropertyGet("Cells",iRows,iCols).OlePropertySet("Value",  
  strRowTemp.c_str());  
  }  
  //画该行的表格边框  
  strRange   =   "A"+IntToStr(iRows)+":F"+IntToStr(iRows);  
  ERange   =   Sheet.OlePropertyGet("Range",strRange.c_str());  
  EBorders   =   ERange.OlePropertyGet("Borders");  
  EBorders.OlePropertySet("linestyle",xlContinuous);  
  EBorders.OlePropertySet("weight",xlThin);  
  EBorders.OlePropertySet("colorindex",xlAutomatic);  
  iRows++;  
  Query1->Next();  
  }//while结束  
   
  Wb.OleProcedure("Save");//保存表格  
  Wb.OleProcedure("Close");关闭表格  
  Ex.OleFunction("Quit");退出Excel  
  //定义目标文件名  
  AnsiString   DestinationFile   =  
  GetCurrentDir()+"\\report\\table.xls";  
  //将刚刚修改的Excel表格文件table.xls拷贝到report目录下  
  if(!CopyFile(ExcelFileName.c_str(),DestinationFile.c_str(),false))  
  {  
  Application->MessageBox("复制文件操作失败,Excel文件可能正在使用中!",  
  "错误",MB_ICONSTOP|MB_OK);  
  return;  
  }  
  Application->MessageBox("成功完成报表保存!\n可以按\打开Excel文件\  
  按钮进行报表工作","提示",MB_ICONINFORMATION|MB_OK);  
   
  SaveButton   ->Enabled   =   true;  
  ReadButton   ->Enabled=true;  
  }//try结束  
  catch(...)  
  {  
  Application->MessageBox("操作Excel表格失败!",  
  "错误",MB_ICONSTOP|MB_OK);  
  Wb.OleProcedure("Close");  
  Ex.OleFunction("Quit");  
  SaveButton   ->Enabled   =   true;  
  ReadButton   ->Enabled=false;  
  }  
  }  
  至此,完成报表数据的写入工作。如果要对完成的Excel表进行操作,可以点击“打开Excel表文件按钮”(ReadButton),进行修改,保存,打印等操作。ReadButton的单击事件如下实现:  
  void   __fastcall   TForm1::   ReadButtonClick(TObject   *Sender)  
  {  
  try  
  {  
  //指定report目录下的报表文件用于用户操作  
  AnsiString   ExcelFileName   =    
  GetCurrentDir();+"\\report\\table.xls";  
   
  if(!FileExists(ExcelFileName))  
  {  
  Application->MessageBox("Excel表文件不存在,无法打开!",  
  "错误",MB_ICONSTOP|MB_OK);  
  return;  
  }  
   
  try  
  {  
  Ex   =   Variant::CreateObject("Excel.Application");  
  }  
  catch(...)  
  {  
  Application->MessageBox("无法启动Excel","错误",MB_ICONSTOP|MB_OK);  
  return;  
  }  
  //使Excel可见  
  Ex.OlePropertySet("Visible",true);  
  //打开Excel表格文件Table.xls  
  Ex.OlePropertyGet("WorkBooks").OleProcedure("Open",ExcelFileName.c_str());  
  }  
  catch(...)  
  {  
  Application->MessageBox("操作Excel表格错误!","错误",MB_ICONSTOP|MB_OK);  
  Ex.OleFunction("Quit");  
  }  
  }  
   
  以上关于C++BuilderExcel表格的操作仅作为个人观点和水平呈献给关心此问题的读者,如果有更好的方式方法,敬请指教,不胜感激。  
   
   
 

NO.4   作者: skyclin

不推荐你全部按照用户的方法去做!  
  要换个角度来说明你的解决方案比用户自己的方法好!

NO.5   作者: bigbigfans

同意:zjhydx98(tourist)     的说法  
  用户恨不得软件的界面和操作Excel一模一样,那只能尽量模仿,毕竟这样用户用起来感觉会舒服很多

NO.6   作者: WnEunfn

但用起来怪怪的,老是觉得很容易出现问题:  
   
  不是觉得,是的确很容易出现问题,我看老兄你还是准备一个人,将来给客户调节数据库吧……


 ·关于asp与sql触发子的问题    »显示摘要«
    摘要: 问题是这样的.在数据库中有两个数据表. table 1 ==================================== userid | username | userclass /* 分别存放用户id号,用户名,用户权限数据为table 2 中的classflag*/ table 2 ==================================== classid | ......
» 本期热门文章:

©2000-2007 All Rights Reserved. 最佳浏览:1024X768 MSIE