zoukankan      html  css  js  c++  java
  • C#中实现对Excel特定文本的搜索

     

    打开Excel的VBA帮助,查看Excel的对象模型,很容易找到完成这个功能需要的几个集合和对象:

    Application、Workbooks、 Workbook、Worksheets还有Worksheet和Range。

    Application创建Excel应用,Workbooks打开 Excel文档,Workbook获得Excel文档工作薄,Worksheets操作工作表集合,Worksheet获得单个工作表。
    搜索的思路对应上述集合和对象,可以这样表述:要搜索的文本可能存在Excel文档当中的某个工作表上,搜索应该遍历目标Excel文件的每个工作表中的有效区域,如果找到,则退出本次搜索,如果没有找到,则继续搜索直到完成本次搜索。   

    跟Word对象模型不一样的是,Excel对象模型没有提供Find对象,不过没有关系,可以通过两种方法来实现,一个是通过Range对象的Find() 方法来实现; 另外一个比较麻烦,取得工作表Worksheet的有效区域UsedRange之后,遍历该Range对象中的所有行列。实际开发中,用第二 种方法时发现了一个特别的现象,所以第二种方法也准备详细记述一下。   

    1. 打开Excel文档:

      object filename="";
      object MissingValue=Type.Missing;
      string strKeyWord=""; //指定要搜索的文本,如果有多个,则声明string[]
      Excel.Application ep=new Excel.ApplicationClass();
      Excel.Workbook ew=ep.Workbooks.Open(filename.ToString(),MissingValue,
       MissingValue,MissingValue,MissingValue,
       MissingValue,MissingValue,MissingValue,
       MissingValue,MissingValue,MissingValue,
       MissingValue,MissingValue,MissingValue,
       MissingValue);
    

    2. 准备遍历Excel工作表

    2.1 方法1

      Excel.Worksheet ews;
      int iEWSCnt=ew.Worksheets.Count;
      int i=0,j=0;
      Excel.Range oRange;
      object oText=strKeyWord.Trim().ToUpper();
      
      for(i=1;i<=iEWSCnt;i++)
      {
       ews=null;
       ews=(Excel.Worksheet)ew.Worksheets[i];
       oRange=null;
       (Excel.Range)oRange=((Excel.Range)ews.UsedRange).Find(
       oText,MissingValue,MissingValue,
       MissingValue,MissingValue,Excel.XlSearchDirection.xlNext,
       MissingValue,MissingValue,MissingValue);
       if (oRange!=null && oRange.Cells.Rows.Count>=1 && oRange.Cells.Columns.Count>=1)
       {
       MessageBox.Show("文档中包含指定的关键字!","搜索结果",MessageBoxButtons.OK);
       break;
       }
      } 
    

    这里要说两个值得注意的地方。一个是遍历工作表的索引,不是从0开始,而是从1开始;另外一个是Find方法的第六个参数 SearchDirection,指定搜索的方向,帮助文档中说这个参数是可选项,但是我用MissingValue如论如何编译不能通过,不知什么原 因,于是显式指定它的默认值xlNext。

    2.2 方法2
    第一种方法实现了,再看看第二种方法。这种方法除了要遍历工作表,还要对工作表使用区域的行和列进行遍历。其它一样,只对遍历说明,代码如下:

      bool blFlag=false;
      int iRowCnt=0,iColCnt=0,iBgnRow,iBgnCol; 
      for(m=1;m<=iEWSCnt;m++)
      {
       ews=(Excel.Worksheet)ew.Worksheets[m];
       iRowCnt=0+ews.UsedRange.Cells.Rows.Count;
       iColCnt=0+ews.UsedRange.Cells.Columns.Count;
       iBgnRow=(ews.UsedRange.Cells.Row>1)? ews.UsedRange.Cells.Row-1:ews.UsedRange.Cells.Row;
       iBgnCol=(ews.UsedRange.Cells.Column>1)? ews.UsedRange.Cells.Column-1:ews.UsedRange.Cells.Column;
      
       for(i=iBgnRow;i
       {
       for(j=iBgnCol;j
       {
       strText=((Excel.Range)ews.UsedRange.Cells[i,j]).Text.ToString();
       if (strText.ToUpper().IndexOf(strKeyWord.ToUpper())>=0)
       {
       MessageBox.Show("文档中包含指定的关键字!","搜索结果",MessageBoxButtons.OK);
       }
       }
       }
      } 
    

     显然这种方法比第一种繁琐得多,不过这里有一个关于遍历单元格的索引很特别的地方,当工作表中的使用区域UsedRange为单行单列的时候,对 UsedRange中的单元格遍历起始索引值为1,为多行多列的时候,起始索引值为0,不知这是Excel程序设计者出于什么样的考虑?

    2.3 方法二补充案例

    有效数据的行列数,可以通过下面的代码获取。

     nUsedRow = sheet.UsedRange.Rows.Count;
     nUsedCol =  sheet.UsedRange.Columns.Count;

    本文表示对参考文章1,文章2.2中原作者所说的那种奇怪的现象表示质疑,并不会出现那种情况。 2016-8-27

    准备工作

    private void createOutputFile(string excelFullFilename)
            {
                bool isAutoFit = true;
                bool isHeaderBold = true;
                
                Excel.Application xlApp = new Excel.Application();
                Excel.Workbook xlWorkBook;
                Excel.Worksheet xlWorkSheet;
    
                object misValue = System.Reflection.Missing.Value;
                xlApp = new Excel.ApplicationClass();
                xlWorkBook = xlApp.Workbooks.Add(misValue);
                xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
    
                const int excelRowHeader = 1;
                const int excelColumnHeader = 1;
                
                //save header
                int curColumnIdx = 0 + excelColumnHeader;
                int rowIdx = 0 + excelRowHeader;
    
                xlWorkSheet.Cells[rowIdx, curColumnIdx++] = "Title";
                xlWorkSheet.Cells[rowIdx, curColumnIdx++] = "Description";
                const int constBullerLen = 5;
                for (int bulletIdx = 0; bulletIdx < constBullerLen; bulletIdx++)
                {
                    int bulletNum = bulletIdx + 1;
                    xlWorkSheet.Cells[rowIdx, curColumnIdx + bulletIdx] = "Bullet" + bulletNum.ToString();
                }
                curColumnIdx = curColumnIdx + constBullerLen;
                const int constImgNameListLen = 5;
                for (int imgIdx = 0; imgIdx < constImgNameListLen; imgIdx++)
                {
                    int imgNum = imgIdx + 1;
                    xlWorkSheet.Cells[rowIdx, curColumnIdx + imgIdx] = "ImageFilename" + imgNum.ToString();
                }
                curColumnIdx = curColumnIdx + constImgNameListLen;
                xlWorkSheet.Cells[rowIdx, curColumnIdx++] = "HighestPrice";
                xlWorkSheet.Cells[rowIdx, curColumnIdx++] = "OneSellerIsAmazon";
                xlWorkSheet.Cells[rowIdx, curColumnIdx++] = "ReviewNumber";
                xlWorkSheet.Cells[rowIdx, curColumnIdx++] = "IsBestSeller";
    
                //formatting
                //(1) header to bold
                if (isHeaderBold)
                {
                    Range headerRow = xlWorkSheet.get_Range("1:1", System.Type.Missing);
                    headerRow.Font.Bold = true;
                }
                //(2) auto adjust column width (according to content)
                if (isAutoFit)
                {
                    Range allColumn = xlWorkSheet.Columns;
                    allColumn.AutoFit();
                }
    
                //output
                xlWorkBook.SaveAs(excelFullFilename,
                                    XlFileFormat.xlWorkbookNormal,
                                    misValue,
                                    misValue,
                                    misValue,
                                    misValue,
                                    XlSaveAsAccessMode.xlExclusive,
                                    XlSaveConflictResolution.xlLocalSessionChanges,
                                    misValue,
                                    misValue,
                                    misValue,
                                    misValue);
                xlWorkBook.Close(true, misValue, misValue);
                xlApp.Quit();
    
                crl.releaseObject(xlWorkSheet);
                crl.releaseObject(xlWorkBook);
                crl.releaseObject(xlApp);
            }
    View Code

    现在需要用C#去打开已经存在的一个excel,并且找到最后一行,然后按行,继续添加内容。

    private void appendInfoToFile(string fullFilename, AmazonProductInfo productInfo)
            {
                Excel.Application xlApp;
                Excel.Workbook xlWorkBook;
                Excel.Worksheet xlWorkSheet;
                object missingVal = System.Reflection.Missing.Value;
    
                xlApp = new Microsoft.Office.Interop.Excel.Application();
                //xlApp.Visible = true;
                //xlApp.DisplayAlerts = false;
    
                //http://msdn.microsoft.com/zh-cn/library/microsoft.office.interop.excel.workbooks.open%28v=office.11%29.aspx
                xlWorkBook = xlApp.Workbooks.Open(
                    Filename : fullFilename,
                    //UpdateLinks:3,
                    ReadOnly : false,
                    //Format : 2, //use Commas as delimiter when open text file
                    //Password : missingVal,
                    //WriteResPassword : missingVal,
                    //IgnoreReadOnlyRecommended: false, //when save to readonly, will notice you
                    Origin: Excel.XlPlatform.xlWindows, //xlMacintosh/xlWindows/xlMSDOS
                    //Delimiter: ",",  // usefule when is text file
                    Editable : true,
                    Notify : false,
                    //Converter: missingVal, 
                    AddToMru: true, //True to add this workbook to the list of recently used files
                    Local: true,
                    CorruptLoad: missingVal //xlNormalLoad/xlRepairFile/xlExtractData
                    );
    
                //Get the first sheet
                xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); //also can get by sheet name
                Excel.Range range = xlWorkSheet.UsedRange;
                //int usedColCount = range.Columns.Count;
                int usedRowCount = range.Rows.Count;
    
                const int excelRowHeader = 1;
                const int excelColumnHeader = 1;
    
                //int curColumnIdx = usedColCount + excelColumnHeader;
                int curColumnIdx = 0 + excelColumnHeader; //start from column begin
                int curRrowIdx = usedRowCount + excelRowHeader; // !!! here must added buildin excelRowHeader=1, otherwise will overwrite previous (added title or whole row value)
    
                xlWorkSheet.Cells[curRrowIdx, curColumnIdx++] = productInfo.title;
                xlWorkSheet.Cells[curRrowIdx, curColumnIdx++] = productInfo.description;
    
                const int constBullerLen = 5;
                int bulletListLen = 0;
                if (productInfo.bulletArr.Length > constBullerLen)
                {
                    bulletListLen = constBullerLen;
                }
                else
                {
                    bulletListLen = productInfo.bulletArr.Length;
                }
                for (int bulletIdx = 0; bulletIdx < bulletListLen; bulletIdx++)
                {
                    xlWorkSheet.Cells[curRrowIdx, curColumnIdx + bulletIdx] = productInfo.bulletArr[bulletIdx];
                }
                curColumnIdx = curColumnIdx + bulletListLen;
    
                const int constImgNameListLen = 5;
                int imgNameListLen = 0;
                if (productInfo.imgFullnameArr.Length > constImgNameListLen)
                {
                    imgNameListLen = constImgNameListLen;
                }
                else
                {
                    imgNameListLen = productInfo.imgFullnameArr.Length;
                }
                for (int imgIdx = 0; imgIdx < imgNameListLen; imgIdx++)
                {
                    xlWorkSheet.Cells[curRrowIdx, curColumnIdx + imgIdx] = productInfo.imgFullnameArr[imgIdx];
                }
                curColumnIdx = curColumnIdx + imgNameListLen;
    
                xlWorkSheet.Cells[curRrowIdx, curColumnIdx++] = productInfo.highestPrice;
                xlWorkSheet.Cells[curRrowIdx, curColumnIdx++] = productInfo.isOneSellerIsAmazon;
                xlWorkSheet.Cells[curRrowIdx, curColumnIdx++] = productInfo.reviewNumber;
                xlWorkSheet.Cells[curRrowIdx, curColumnIdx++] = productInfo.isBestSeller;
    
                ////http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=ZH-CN&k=k%28MICROSOFT.OFFICE.INTEROP.EXCEL._WORKBOOK.SAVEAS%29;k%28SAVEAS%29;k%28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV3.5%22%29;k%28DevLang-CSHARP%29&rd=true
                //xlWorkBook.SaveAs(
                //    Filename: fullFilename,
                //    ConflictResolution: XlSaveConflictResolution.xlLocalSessionChanges //The local user's changes are always accepted. 
                //    //FileFormat : Excel.XlFileFormat.xlWorkbookNormal
                //);
    
                //if use above SaveAs -> will popup a window ask you overwrite it or not, even if you have set the ConflictResolution to xlLocalSessionChanges, which should not ask, should directly save
                xlWorkBook.Save();
    
                //http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=ZH-CN&k=k%28MICROSOFT.OFFICE.INTEROP.EXCEL._WORKBOOK.CLOSE%29;k%28CLOSE%29;k%28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV3.5%22%29;k%28DevLang-CSHARP%29&rd=true
                xlWorkBook.Close(SaveChanges : true);
    
                crl.releaseObject(xlWorkSheet);
                crl.releaseObject(xlWorkBook);
                crl.releaseObject(xlApp);
            }
    View Code

    参考文章

    1.C#编程实现Excel文档中搜索文本内容的方法及思路 ,2013-7

    2.How to append existing excel file using C# ?

    3.MSDN, Workbooks.Open Method

    4. C#读取excel文件,并且追加内容到最后一行

  • 相关阅读:
    微服务架构技术栈选型手册(万字长文)
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    MFC对话框中使用CHtmlEditCtrl
    ATL开发 ActiveX控件的 inf文件模板
    ActiveX: 如何用.inf和.ocx文件生成cab文件
    Xslt 1.0中使用Array
    如何分隔两个base64字符串?
    An attempt was made to load a program with an incorrect format
    JQuery 公网 CDN
  • 原文地址:https://www.cnblogs.com/arxive/p/5813901.html
Copyright © 2011-2022 走看看