我有一些数据,我想循环处理任何包含任何内容或错误的单元格。
我尝试过的代码如下,它给了我一个Type mismatch
,因为我无法将Error 2042
与vbNullString
进行比较。
' // doesn't work when value is #NA
For row = 1 To 10
If Sheet1.Cells(row, 1) = vbNullString Or IsError(Sheet1.Cells(row, 1)) Then
'do something
End If
Next row
首先,我尝试在Or
中切换逻辑,看看它是否在找到do something
后立即跳至True
,但它会先评估两个语句。
我已经想到了其他一些方法,但它们似乎都不是最好的方法。我确定必须有一个简单,干净的方法来做到这一点?
' Option 1
For row = 1 To 10
If IsError(Sheet1.Cells(row, 1)) Then
'do something
ElseIf Sheet1.Cells(row, 1) = vbNullString Then
'do the same stuff
End If
Next row
'Option 2
For row = 1 To 10
On Error Resume Next
If Sheet1.Cells(row, 1) = vbNullString Then
On Error GoTo 0
'do something
End If
Next row
'Option 3
Dim testValue As Variant
If IsError(Sheet1.Cells(row, 1)) Then
testValue = vbNullString
Else
testValue = Sheet1.Cells(row, 1)
End If
For row = 1 To 10
If testValue = vbNullString Then
'do something
End If
Next row
也许选项2是最好的,但对于任何阅读我的代码的人来说,它并没有多大意义(同样,我也不想失去真正的错误)。
出于测试目的,您可以假设我的数据看起来像这样(A1:A10
)
1
2
4
#N/A
6
#N/A
9
10
答案 0 :(得分:1)
我会选择选项1但你可以试试这个。顺便说一下,不要将Row用作变量名,因为它是VBA属性。 (并且如果没有,请不要问我为什么会这样。)
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.utils.ByteArray;
import flash.utils.*;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.net.URLLoaderDataFormat;
import flash.events.*;
import flash.net.URLStream;
public class Check_Bytes_Image_v1 extends MovieClip
{
public var bytes :ByteArray = new ByteArray();
public var stream :URLStream = new URLStream();
public var loader :Loader = new Loader();
public var formatFound : Boolean = false;
public var str_Format : String = "";
public var str_Search : String = "";
public var tempStr : String = "";
public var tempUInt : uint = 0;
public var bytePos : int = 0;
public var searchString:String = "";;
public var searchArray:Array = new Array();
public function Check_Bytes_Image_v1()
{
//# add canvas
addChild(loader);
//# load image bytes via URLStream
stream.addEventListener(ProgressEvent.PROGRESS, onStreamProgress);
stream.addEventListener(Event.COMPLETE, completeHandler);
stream.load(new URLRequest("image1.png")); //image1.png
}
public function onStreamProgress(evt:ProgressEvent):void
{ evt.target.readBytes(bytes, bytes.length, evt.target.bytesAvailable); }
public function completeHandler(evt:Event):void
{
//bytes_toString(bytes); //if you want to check hex output
//# update a string with format type
str_Format = checkImageFormat( bytes );
trace("Image format is : " + str_Format );
searchString = "89 50 4E 47"; //use any known sequential bytes in your Array
bytePos = indexOfBytes( bytes, searchString );
trace("bytes begin at : " + bytePos);
bytes.position = 0; //reset to starting pos
loader.loadBytes(bytes); //decode & display image
trace("loaded image now...");
//bytes.clear(); //empty the bytes
}
//# findBytes (byteArray:ByteArray, value:String, startPosition:int = 0, endPosition:int = 0, endian:String = null):int
public function indexOfBytes (byteArray:ByteArray, value:String, startPosition:int = 0, endPosition:int = 0, endian:String = null):int
{
str_Search = value;
trace("str_Search v1 is " + str_Search);
//# Clean up possible hex notation
str_Search = str_Search.split("0x").join("");
str_Search = str_Search.split(".").join("");
str_Search = str_Search.split("/").join("");
//# Clean up hex (remove non Alpha-Numeric, white spaces, new line, etc)
str_Search = str_Search.replace(/\W+/g, ""); //# clear all non Alpha-Numeric chars
str_Search.toUpperCase(); //# convert to uppercase
trace("str_Search v2 is " + str_Search);
tempUInt = 0; searchArray = []; //# resets
//# convert input string into two-digits-per-slot array
while ( tempUInt < str_Search.length)
{
searchArray.push(str_Search.substring(tempUInt, Math.min(tempUInt+2, str_Search.length) ) );
tempUInt += 2;
}
trace("searchArray length is : " + searchArray.length);
//# search bytes for same hex vlues
//# Resets for WHILE loop
if ( startPosition != 0) { bytePos = startPosition; }
else { bytePos = 0; }
tempUInt = 0;
while (byteArray.bytesAvailable)
{
//# safety check : Stop at limit of bytes range
if ( endPosition != 0 ) //# Don't go over end pos if not null
{
if ( byteArray.position >= endPosition )
{
trace("reached end position of search : stopping at: " + byteArray.position );
break;
}
}
else //# Don't go over total bytes length
{
if ( byteArray.position > (byteArray.length - searchArray.length) )
{
trace("reached ENDing bytes of search : stopping at: " + byteArray.position );
break;
}
} //# end safety check...
//# Find search values
byteArray.position = bytePos;
tempStr = byteToHex( byteArray.readUnsignedByte() );
tempUInt = 0; //reset for TRUE count
if ( tempStr == searchArray[0] )
{
//# tempUInt to count how many times it was true
//# if total true's == search array length then we found match
//trace("-------------------------------------------");
for (var i:int = 0; i <= searchArray.length-1; i++)
{
bytePos = byteArray.position-1;
if ( byteToHex( byteArray[bytePos+i] ) == searchArray[i] )
{
//trace("bytes [" +bytePos+ " + " +i+ "] is : " + byteToHex( byteArray[bytePos+i] ) );
//trace("search array [" +i+ "] is : " + searchArray[i] );
tempUInt++; //# add +1 for each matching entry for both arrays
}
}
trace("tempUInt match is : " + tempUInt + " || Expected TRUE count : " + searchArray.length );
if ( tempUInt == searchArray.length )
{
tempUInt = byteArray.position - 1;
trace("match FOUND for search at pos : " + tempUInt);
break;
}
else
{
tempUInt = int(-1);
trace("match NOT found for search... current pos : " + ( byteArray.position-1) );
}
}
bytePos++;
} //# end WHILE loop
return tempUInt;
}
public function byteToHex ( input:uint ) : String
{
tempStr = input.toString(16);
if(tempStr.length < 2) { tempStr = "0" + tempStr; } //# zero padding if 1 char only
return tempStr.toUpperCase();
}
public function checkImageFormat ( inputBA : ByteArray ) : String
{
//# If you need to READ as specific Endianness of format
//# default in AS3 is BIG ENDIAN type
//inputBA.endian = Endian.LITTLE_ENDIAN;
//inputBA.endian = Endian.BIG_ENDIAN;
formatFound = false; bytePos = 0;
while( formatFound == false) //* keep going until BREAK action
{
if ( formatFound == true ){ trace("## Found format..."); break; }
inputBA.position = bytePos; //* reset positions
tempUInt = inputBA.readUnsignedByte(); //* READ byte = check byte value as Int
bytePos = inputBA.position; //* update Pos to new offset move caused by READ action
//# Check for JPG (begins xFF xD8 xFF xE0)
if (tempUInt == 0xFF)
{
inputBA.position = bytePos-1; //* go back one byte to include FF in next check
tempUInt = inputBA.readUnsignedInt(); //* READ 4 bytes at once (expect FF-D8-FF-E0)
//trace ("tempUInt check : " + tempUInt);
if (tempUInt == 0xFFD8FFE0 ) //* check IF EQUAL to expected value
{
inputBA.position += 2; //skip 2 bytes ahead to expected pos of JFIF
tempUInt = inputBA.readUnsignedInt(); //* now check next 4 bytes
if (tempUInt == 0x4A464946) //* if expected JFIF (as hex) value
{
str_Format = "jpg";
trace("found JPG start + JFIF header..."); formatFound = true;
}
}
} //# end Check for JPG
//# Check for PNG (begins x89 x50 x4E x47)
if (tempUInt == 0x89)
{
inputBA.position = bytePos-1; //* go back one byte to include 89 in next check
tempUInt = inputBA.readUnsignedInt(); //* READ 4 bytes at once (expect 89-50-4E-47)
//trace ("tempUInt check : " + tempUInt);
if (tempUInt == 0x89504E47 ) //* check IF EQUAL to expected value
{
tempUInt = inputBA.readUnsignedInt(); //* now check next 4 bytes
if (tempUInt == 0x0D0A1A0A) //* if also expected value
{
inputBA.position += 4; //skip 4 bytes ahead to expected pos of IHDR
tempUInt = inputBA.readUnsignedInt(); //* now check next 4 bytes
if (tempUInt == 0x49484452) //* if expected IHDR (as hex) value
{
str_Format = "png";
trace("found PNG start + IHDR header..."); formatFound = true;
}
}
}
} //# end Check for PNG
//# Increment Pos for next byte value checking at top of While loop
bytePos++;
} //# end WHILE loop
return str_Format;
}
public function bytes_toString ( ba:ByteArray ) : String
{
//trace("checking args : " + args);
tempStr = ""; var str_Hex:String = ""; var len:uint = ba.length;
ba.position = 0;
for (var i:uint = 0; i < len; i++)
{
tempStr=ba.readUnsignedByte().toString(16);
if(tempStr.length<2) { tempStr="0"+tempStr; } //# zero-padding if 1 char only
str_Hex += tempStr ;
}
return str_Hex.toUpperCase();
}
public function bytes_toInt( ...args ) : int
{
var temp_conv_ba : ByteArray = new ByteArray();
for (var i:uint = 0; i < args.length; i++)
{ temp_conv_ba[i] = args[i]; }
var int_fromBytes:int = int("0x" + bytes_toString(temp_conv_ba) );
return int_fromBytes;
}
} //# end class
} //# end package
答案 1 :(得分:1)
编辑以添加第二种方法
AutoFilter()
的方法:
With Sheet1 '<--| reference your sheet
With .Range("A1", .Cells(.Rows.Count, "A").End(xlUp)) '<--| reference its column A cells from row 1 down to last not empty one
.AutoFilter Field:=1, Criteria1:="", Operator:=xlOr, Criteria2:="#N/A" '<--| filter referenced range on its 1st (and only) column with "" or "#N/A" values
If Application.WorksheetFunction.Subtotal(103, .Cells) > 1 Then '<--| if any filterd cells other than header
With .Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible) '<--| reference filtered cells skipping header
'do something with referenced range containing all wanted values
End With
End If
End With
.AutoFilterMode = False
End With
SpecialCells()
方法:
Dim myRng As Range
With Sheet1
Set myRng = GetErrorsAndBlanks(.Range("A1", .Cells(.Rows.Count, "A").End(xlUp)))
If Not myRng Is Nothing Then
'do something with 'myRng'
End If
End With
您使用以下GetErrorsAndBlanks
()函数:
Function GetErrorsAndBlanks(rng As Range) As Range
With rng
Set GetErrorsAndBlanks = .Resize(1, 1).Offset(.Rows.Count, .Columns.Count) '<--| initialize select range with a dummy cell, to be taken away before exiting
On Error Resume Next
Set GetErrorsAndBlanks = Union(GetErrorsAndBlanks, .SpecialCells(xlCellTypeConstants, xlErrors)) '<--| try and get "error" cells deriving from constants
Set GetErrorsAndBlanks = Union(GetErrorsAndBlanks, .SpecialCells(xlCellTypeFormulas, xlErrors)) '<--| try and get "error" cells deriving from formulas
Set GetErrorsAndBlanks = Union(GetErrorsAndBlanks, .SpecialCells(xlCellTypeBlanks)) '<--| try and get "blank" cells
Set GetErrorsAndBlanks = Intersect(GetErrorsAndBlanks, .Cells) '<--| take "dummy" cell away
End With
End Function
答案 2 :(得分:1)
只需创建自己的数据验证功能并调用:
Public Function IsEmptyOrError(test As Variant) As Boolean
If IsError(test) Then Exit Function
IsEmptyOrError = CStr(test) = vbNullString
End Function
致电代码:
For Row = 1 To 10
If IsEmptyOrError(Sheet1.Cells(row, 1)) Then
'do something
End If
Next Row