2013-10-16 63 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