2011-12-08 67 views
2

我正在做一個測試,在讀取excel文件時,檢查單元格的格式和值。讀取excel文件,檢查格式和值是否正確

我需要專門檢查這些東西:

  • 可樂具有整數
  • COLB已整數格式化爲0001,0012,等等
  • 感冒應該有一個整數,如果COLC有1
  • colE應該有一個4位數的時鐘像0300

這裏的正確方法是什麼?

現在我正在製作功能檢查像整數:

Int(sheet.Cells(row, col)) = sheet.Cells(row, col)  

這將檢查的整數值,但什麼檢查所有其他的事情的最好方法? 我聽說過一個我可以使用的驗證器對象。

任何人有任何關於這個問題的技巧?

+0

對於A,D,E數據驗證應該工作(數據選項卡,數據驗證)。用於具有數據驗證的B輸入掩碼。它將首先防止數據錯誤。但如果你不能這樣做,那麼VBA將是必需的。 – xQbert

+0

可以說我沒有控制輸入文件。我用vba讀取它並檢查錯誤,在vba中使用自動驗證程序的任何方法? – d0lph1n

+0

你想在編輯時檢查一個新的excel文件(從excel內),還是你必須檢查一大堆已經存在的excel文件(例如導入/批量加載到數據庫中)?它是否必須是VBA? – knb

回答

4

此代碼根據您的規則驗證ActiveSheet。對於B列,我理解你的意思是該值實際上是文本,而不是該單元格用前導零格式化。

Sub Validate() 
    Dim lRow As Long 
    Dim lNumRows As Long 
    Dim bRowValid As Boolean 
    Dim bSheetValid As Boolean 

    With ActiveSheet 
     bSheetValid = True ' initial assumption is sheet is valid 
     lNumRows = .Cells(.Rows.Count, 1).End(xlUp).Row 
     For lRow = 2 To lNumRows 
      bRowValid = IsInteger(.Cells(lRow, 1).Value) 
      bRowValid = bRowValid And IsFormatted(.Cells(lRow, 2).Value) 
      If .Cells(lRow, 3).Value = 1 Then 
       bRowValid = bRowValid And IsInteger(.Cells(lRow, 4).Value) 
      End If 
      bRowValid = bRowValid And IsTime(.Cells(lRow, 5).Value) 
      bSheetValid = bSheetValid And bRowValid 
      If Not bRowValid Then 
       ' do something here if you want to flag this row 
      End If 
     Next lRow 
    End With 

    If bSheetValid Then 
     ' copy data to historical sheet 
    End If 
End Sub 
Function IsInteger(vValue As Variant) As Boolean 
    If VarType(vValue) = vbDouble Then 
     IsInteger = (Fix(vValue) = vValue) 
    Else 
     IsInteger = False 
    End If 
End Function 
Function IsFormatted(vValue As Variant) As Boolean 
    If VarType(vValue) = vbString Or VarType(vValue) = vbDouble Then 
     IsFormatted = vValue Like "[0-9][0-9][0-9][0-9]" 
    Else 
     IsFormatted = False 
    End If 
End Function 
Function IsTime(vValue As Variant) As Boolean 
    If IsFormatted(vValue) Then 
     IsTime = IsDate(Left$(vValue, 2) & ":" & Right$(vValue, 2)) 
    Else 
     IsTime = False 
    End If 
End Function 

以下是你可能要考慮一些改變:

  • 更改For...LoopDo...Loop這樣就可以儘快停止無效的數據中找到。如果您不關心哪些行無效,請執行此操作。
  • 如果您想查看錯誤,請爲無效數據添加突出顯示。在If Not bRowValid...塊中執行此操作。
  • Sub Validate更改爲以工作表爲參數並返回boolean的函數。 IOW將驗證與將數據複製到歷史數據表的代碼分開。
+1

它實際上是一個帶前導零的格式化的整數,但你的答案是驚人的,我可以在我的代碼中使用它的大部分。感謝您利用您的時間查看我的問題並解決問題:) – d0lph1n

3

如果你需要解析一個外部文件,這裏有一個小Perl腳本(未經測試從我的頭頂部)。

use Regexp::Common; 
use Test::More; 
#use Spreadsheet::ParseExcel; if using excel <=2003 

use Spreadsheet::XLSX; 


my $excel = Spreadsheet::XLSX -> new ('test.xlsx'); 

foreach my $sheet (@{$excel -> {Worksheet}}) { 


    printf("Sheet: %s\n", $sheet->{Name}); 

    $sheet -> {MaxRow} ||= $sheet -> {MinRow}; 

    foreach my $row ($sheet -> {MinRow} .. $sheet -> {MaxRow}) { 

      $sheet -> {MaxCol} ||= $sheet -> {MinCol}; 

      foreach my $col ($sheet -> {MinCol} .. $sheet -> {MaxCol}) { 

        my $cell = $sheet -> {Cells} [$row] [$col]; 

        if ($cell) { 
        if ($col == 0){ #colA 
         $cell =~ qr/$RE{num}{int}/ or fail "Value '$cell' in cell($row, $col) is not an int"; 
        } 
        if ($col == 1){ #colB 


         int($cell) or fail "Value '$cell' in cell($row, $col) cannot be parsed to an int"; 
         $cell =~ /\d{4}/ or fail "Value '$cell' in cell($row, $col) does not consist of 4 digits"; # must they be consecutive? 


        } 
        if ($col == 3){ #D 
          my $cellC = $sheet -> {Cells} [$row] [$col - 1] 
          if ($cellC == 1){ 
          $cell =~ qr/$RE{num}{int}/ or fail "Value '$cell' in cell($row, $col) is not an int although ColC is 1 "; 
          } 

        } 
        # one more test for colE 
        } 

      } 
    } 
} 
done_testing(); 

對於colE測試,您必須找到自己的模式/正則表達式,但這不應該太難。 用於檢查perl中的時間值,請參閱: http://metacpan.org/pod/Regexp::Common::time 雖然我沒有使用過這個模塊。

http://metacpan.org/pod/Regexp::Common

在VBA看你需要加載微軟正則表達式類型庫(其自帶的Windows預安裝)。整個VBA代碼將與我上面的僞代碼類似,但更詳細。

+2

一個自發的perl腳本!多麼奇怪的建議! –

+0

從來沒有嘗試perl,但它看起來像做我的意圖。但是我期望的是在excel中的一些語法和函數來幫助我去。仍然你得到upvote :)謝謝 – d0lph1n

+0

@ jean-françois-corbett:實際上,我組合了兩個模板:外部循環來自Spreadsheet :: XLSX的perldoc的「Synopsis」部分。 「if」塊內的測試來自Regexp :: Common的perldoc。我只寫了正則表達式(可以進一步簡化)。此外,我爲我自己的日常工作做了類似的事情(在perl中讀寫excel文件)。 – knb

相關問題