检查错误或vbNullString类型不匹配

时间:2017-01-13 17:09:22

标签: excel vba excel-vba

我有一些数据,我想循环处理任何包含任何内容或错误的单元格。

我尝试过的代码如下,它给了我一个Type mismatch,因为我无法将Error 2042vbNullString进行比较。

' // 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

3 个答案:

答案 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