2013-10-16 65 views
1

我有一个功能,我写在VB中的问题。 该工具将打开一个Excel工作表并且也在该工作表中搜索两个值。用多个搜索参数搜索

Picture of an example from a table

我写的函数,看上去如果在列“M”,并在同一行的列“N”的值是相同的:

的Excel工作表的结构如下

Function twoStrSearch(ByVal criteria1 As String, ByVal criteria2 As String, ByVal strPrimarySearchColumn As String, _ 
         ByVal Offset_Krit2 As Integer, ByVal Offset_result As Integer, _ 
         ByVal objWorksheet As Microsoft.Office.Interop.Excel.Worksheet) As VariantType 
    '******************************************************************************************** 
    'Function for Searching an Excel Sheet. 
    'If the Sheet Contains the two Criterias in the same row it will return the search Value 
    '******************************************************************************************** 
    'Parameter:     Explanation:   
    'criteria1     The first comparison value 
    'criteria2     The second comparison value 
    'strPrimarySearchColumn  The Name of the Row where the first comparsion value is 
    'Offset_Krit2    The Offset Value where the second comparison value is 
    'Offset_Ergebnis   The Offset Value where the Search result is what will be returned 
    'objWorksheet    The object of the Excel Sheet that should be searched in 
    '******************************************************************************************** 

    Dim strAddress As String 
    Dim area As Microsoft.Office.Interop.Excel.Range 
    Dim range As Microsoft.Office.Interop.Excel.Range 
    'Get's the letter of the Column 
    strAddress = objWorksheet.Cells.Find(What:=strPrimarySearchColumn).Address 
    strAddress = Mid(strAddress, 2, 1) 
    area = objWorksheet.Columns(strAddress & ":" & strAddress) 'Range over the Column 
    For Each range In area 
     'If both criteria in the same Row are True then get the result 
     If range.Value2.ToString = criteria1 And range.Offset(0, Offset_Krit2).Value = criteria2 Then 
      twoStrSearch = range.Offset(0, Offset_result).Value 
      Exit Function 
     End If 
    Next 
    twoStrSearch = "--" 'if nothing found result is "--" 
End Function 

的Eroor:如Creterium 1和2,如果是这样的话,它会在列“O”

我的代码看起来像返回值发生在For Each循环中,如果他将Criteria1和2比较Cell值。

我现在坚持了一段时间,我想也许你们中的一些人有一个想法!

+1

'strAddress =中(strAddress,2,1)'这是错误的方式来获得地址。它会失败说'$ AA $ 1' –

+1

另一个提示。 'objWorksheet.Columns(strAddress&“:”&strAddress)'为什么要循环遍历该列中的所有单元格(1048576,如果是xl2007 +)?找到该列的最后一行,然后构建你的内容。 –

+0

@ Siddharth Rout:感谢您的提示与地址。我没有想到这一点。另外我会尽快实施。感谢提示 – Moosli

回答

2

For Each Loop有两个主要问题:它遍历列中的所有范围而未指定实际上需要单元格(列是范围,单元格是一个范围等),默认情况下它假设你想遍历整个列,因此.Value2触发错误(它不能应用于许多单元格)。您也正在使用.ToString而未确认给定单元格中的值不为空(不是Nothing)。更正后的代码:

For Each range In area.Cells 
    'If both criteria in the same Row are True then get the result 
    If (range.Value2 IsNot Nothing) Then 
     If range.Value2.ToString = criteria1 And range.Offset(0, Offset_Krit2).Value = criteria2 Then 
      twoStrSearch = range.Offset(0, Offset_result).Value 
      Exit Function 
     End If 
    End If 
Next 

也有一些其他的问题,你的代码,例如:

strAddress = objWorksheet.Cells.Find(What:=strPrimarySearchColumn).Address 

这条线将在没有找到什么是预期的情况下触发一个错误。更正确的方法是:

strAddress = "" 
Dim tempRange As Microsoft.Office.Interop.Excel.Range = objWorksheet.Cells.Find(What:=strPrimarySearchColumn) 
If (tempRange IsNot Nothing) Then 
    strAddress = tempRange.Address 
End If 

您可以从范围(tempRange)直接将行/列,而不是用目前的方法。请参阅上面的Siddharth Rout的评论。

+0

非常感谢。你说的是对的,现在它工作得很好。你们像往常一样最好。 – Moosli

+0

@Moosli不客气。 – varocarbas

+0

@varoarbas。感谢您的提示与地址。将包含在代码中。 – Moosli

2

不为点(仅用于说明目的)

摘要。

  1. 你提取的地址给你错误如果搜索文本的方式说,山口AA1
  2. 你不需要地址来构建你的范围。您可以使用列号。
  3. 没有点循环尽管所有细胞(1048576在XL2007 +的情况下),通过在搜索栏中找到最后一行构建您的相关范围

比方说,你的数据看起来像这样

enter image description here

代码:(在VS 2010 Ultimate + Office 2010中进行了测试和测试))

试试这个。我已经评论了代码,所以让我知道是否有任何不合理的事情。

Imports Excel = Microsoft.Office.Interop.Excel 

Public Class Form1 
    '~~> Define your Excel Objects 
    Dim xlApp As New Excel.Application 
    Dim xlWorkBook As Excel.Workbook 
    Dim objWorksheet As Excel.Worksheet 

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 
     '~~> Open relevant file 
     xlWorkBook = xlApp.Workbooks.Open("C:\MyFile.xlsx") 

     '~~> Display Excel 
     xlApp.Visible = True 

     '~~> Set your first worksheet 
     objWorksheet = xlWorkBook.Sheets(1) 

     Dim Ret = twoStrSearch("1", "text-x", "TextNumber", -1, 1) 

     MsgBox (Ret) 

     '~~> Close the File 
     xlWorkBook.Close (False) 

     '~~> Quit the Excel Application 
     xlApp.Quit() 

     '~~> Clean Up 
     releaseObject (objWorksheet) 
     releaseObject (xlWorkBook) 
     releaseObject (xlApp) 
    End Sub 

    Function twoStrSearch(ByVal criteria1 As String, ByVal criteria2 As String, ByVal strPrimarySearchColumn As String, 
    ByVal Offset_Krit2 As Integer, ByVal Offset_result As Integer) As String 
     Dim area As Excel.Range = Nothing 
     Dim range As Excel.Range = Nothing 
     Dim aCell As Excel.Range = Nothing 
     Dim ColNo As Integer, lRow As Integer 

     '~~> Find which column as the search text 
     aCell = objWorksheet.Cells.Find(What:=strPrimarySearchColumn) 

     '~~> Set it to "--" in case nothing is found 
     twoStrSearch = "--" 

     '~~> if found 
     If aCell IsNot Nothing Then 
      '~~> Get the column number 
      ColNo = aCell.Column 

      '~~> Get last row of that column 
      lRow = objWorksheet.Cells(objWorksheet.Rows.Count, ColNo).End(Excel.XlDirection.xlUp).Row 

      '~~> Construct your range from row 2 onwards. Row1 has headers 
      area = objWorksheet.range(objWorksheet.Cells(2, ColNo), objWorksheet.Cells(lRow, ColNo)) 

      For Each range In area 
       'If both criteria in the same Row are True then get the result 
       If range.Value2.ToString = criteria1 And range.Offset(, Offset_Krit2).Value = criteria2 Then 
        twoStrSearch = range.Offset(, Offset_result).Value 
        Exit For 
       End If 
      Next 
     End If 

     releaseObject (area) 
     releaseObject (range) 
     releaseObject (aCell) 

     Return twoStrSearch 
    End Function 

    '~~> Release the objects 
    Private Sub releaseObject(ByVal obj As Object) 
     Try 
      System.Runtime.InteropServices.Marshal.ReleaseComObject (obj) 
      obj = Nothing 
     Catch ex As Exception 
      obj = Nothing 
     Finally 
      GC.Collect() 
     End Try 
    End Sub 
End Class 

输出:

enter image description here

+1

尽管不是积分,它确实值得+1 :) – varocarbas

+0

@varocarbas:谢谢。你很亲切:) –

+0

好的谢谢你,我应该得到一个+1。现在我知道你的意思了。 刚刚意识到该函数需要一点点时间才能通过17000行;) – Moosli