我在这里做一个关于读取excel文件的测试,检查单元格的格式和值。
我需要具体检查这些事情:
这里有正确的方法吗?
现在我正在制作检查整数的函数,如:
Int(sheet.Cells(row, col)) = sheet.Cells(row, col)
这将检查整数值,但是检查所有其他内容的最佳方法是什么? 我听说过我可以使用的验证器对象。
有人对这个问题有什么窍门吗?
答案 0 :(得分: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...Loop
更改为Do...Loop
,以便在找到无效数据后立即停止。如果您不在乎知道哪些行无效,请执行此操作。If Not bRowValid...
块中执行此操作。Sub Validate
更改为将工作表作为参数并返回boolean
的函数。 IOW,将验证与将数据复制到历史表的代码分开。答案 1 :(得分: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中,您必须加载Microsoft正则表达式类型库(预先安装在Windows上)。整个VBA代码与上面的伪代码类似,但更详细。