vbamania.pl
login:
hasło:
 
  *Rejestracja *Zapomniane hasło
 Dziś jest sobota, 03 maja 2025 roku.
Ustaw jako stronę startową Ulubione Napisz
PowrótPowrót do serwisu  RegulaminRegulamin rssRSS

  tytuł wątku:
Wątki dyskusji

sprawdzić czy w zakresie lub arkuszu jest komórka z błędem - arkusz zabezpieczony ponad 40000 wierszy kilkanaście kolumn


otwartyotwarty rozpoczął: LAnd postów: 13



napisał: jalamas
postów: 316


umieszczony:
28 czerwca 2007
09:50

  
A istotą tego rozwiąznia jest nie tylko to, że jest w tablicy (szybciej), lecz także IsError, a nie Find jakiekolwiek by nie były argumenty Find
Cytat:
ErrArr = Array("#DIV/0!", "#N/A!"....

które nieustająco dołączałeś w takiej czy innej wersji:
Cytat:
dtrng.Find(ele, , xlValues, xlWhole

bo powyższe może być źródłem niewłaściwej identyfikacji , co jeszcze raz powtarzam
Cytat:
ale nie tędy droga.

Miłej pracy.
napisał: LAnd
postów: 107


umieszczony:
28 czerwca 2007
01:43

edytowany:
28 czerwca 2007
01:51

  
tak się zascukałem sprawdzaniem niżej opisanych wersji że zapomniałem o sugesti r_c sprawdzić tablicę


i BRAWOOO !!!


dopalacz 00:00:01

Sub testDopalacz()
 Debug.Print KomorkiZBledamiAdresyDopalacz(ActiveSheet)
End Sub

Function KomorkiZBledamiAdresyDopalacz(WSh As Worksheet) As String
 'używa funkcji : ObszarDanych i SaKomorkiZBledami
 Dim DataRngAdr, tmpWb As Workbook, oldCalc, oldScrUpd, pocz, TmpSh As Worksheet
 Dim Maxid1, Maxid2, i1, i2, rv, ttt
 pocz = Now 'linia testowa usunąc
 DataRngAdr = ObszarDanych(WSh)
 If Len(DataRngAdr) < 1 Then Exit Function
 If Not SaKomorkiZBledami(WSh) Then Exit Function
  
  ttt = WSh.Range(DataRngAdr)
  Maxid2 = UBound(ttt, 2)
  Maxid1 = UBound(ttt, 1)
  For i1 = 1 To Maxid1
  For i2 = 1 To Maxid2
   If IsError(ttt(i1, i2)) Then rv = rv & "," & Cells(i1, i2).Address(False, False)
  Next
  Next
  KomorkiZBledamiAdresyDopalacz = Mid(rv, 2)
  Debug.Print "dopalacz "; CDate(Now - pocz) 'linia testowa usunąc
End Function

napisał: LAnd
postów: 107


umieszczony:
27 czerwca 2007
22:46

  
dane miałem na arkuszu o nazwie "test"
przegladałem coś na arkuszu o nazwie "Arkusz2"
i uruchomiłem twoją procedurę test

zdziwiłem się że wykonanie funkcji Find nie zgłosiło błędu bo zapis [A1] ( bez kropki) był interpretowany jako adres ActiveSheet ("Arkusz2") więc z innego arkusza niż arkusz wskazywany przez objWSh ("test"). i to wszystko.
napisał: jalamas
postów: 316


umieszczony:
27 czerwca 2007
22:29

edytowany:
27 czerwca 2007
22:36

  
...
napisał: LAnd
postów: 107


umieszczony:
27 czerwca 2007
22:26

  
połączenie kopi danych do tablicy i wklejenia w nowy arkusz
ogromne dzięki za współpracę
zaskoczyło mnie .[A1] w Find - kupuję

we wszystkich procedurach ostrzeżenie że jest to wesja robocz z ograniczoną obsługą błędów
wiersze zablokować lub wykasować


zakres danych A1:P41266 komórki z błędami dopisano na końcu
iteracja 00:00:10
turbo 00:00:03
kopia 00:00:08 do schowka zapisuje z formatami a wartości do wklejania wydłubuje
find 00:00:13 'dwa razy obiega dane dla każdego rodzaju błędu

'iteracja =======================================================================
Sub TestIteracja()
Dim lngRes As Long, pocz
    pocz = Now
    lngRes = CountIsError(ThisWorkbook.Sheets("test")) 'ThisWorkbook.Worksheets(1))
    Debug.Print "iteracja "; CDate(Now - pocz)
    MsgBox lngRes
End Sub
'CountIsError jak w poście z kropką przed .[A1]

'kopiowanie =======================================================================

Sub testKopia()
 Debug.Print KomorkiZBledamiAdresy(ThisWorkbook.Sheets("test"))
End Sub

Function KomorkiZBledamiAdresy(WSh As Worksheet) As String
 Dim DataRngAdr, tmpWb As Workbook, oldCalc, oldScrUpd, pocz
    pocz = Now
  
  MsgBox "wersja robocza nie obsługuje błędów"
  Exit Sub
  
  DataRngAdr = ObszarDanych(WSh)
  If Len(DataRngAdr) < 1 Then Exit Function
  If SaKomorkiZBledami(WSh) Then Exit Function
' oldScrUpd = Application.ScreenUpdating: Application.ScreenUpdating = False
' oldCalc = Application.Calculation: Application.Calculation = xlCalculationManual
  Set tmpWb = Workbooks.Add(xlWBATWorksheet)
  WSh.Range(WSh.Cells(1, 1), WSh.Range(DataRngAdr)).Copy
  tmpWb.Sheets(1).Cells(1, 1).PasteSpecial xlPasteValues
  KomorkiZBledamiAdresy = KomorkiZbledami(tmpWb.Sheets(1))
  tmpWb.Close False
' Application.ScreenUpdating = oldScrUpd
' Application.Calculation = oldCalc

  Debug.Print "kopia "; CDate(Now - pocz)
End Function

'*************** wspólne kopia i turbo ***********************************

Function KomorkiZbledami(WSh As Worksheet) As String
 Dim RetVal As String
  On Error Resume Next
   RetVal = WSh.Cells.SpecialCells(xlCellTypeConstants, xlErrors).Address
   RetVal = RetVal & IIf(Len(RetVal) > 0, ",", "") & WSh.Cells.SpecialCells(xlCellTypeFormulas, xlErrors).Address
  On Error GoTo 0
 KomorkiZbledami = RetVal
End Function

Function SaKomorkiZBledami(WSh As Worksheet) As Boolean
Dim Blad
Set Blad = Nothing
On Error Resume Next
 Blad = Application.Worksheet.Function.Sum(WSh.Cells)
On Error GoTo 0

SaKomorkiZBledami = IsObject(Blad)

End Function


Function ObszarDanych(WSh As Worksheet) As String
 Dim LewaKolumna As Integer, PrawaKolumna As Integer, GornyWiersz As Long, DolnyWiersz As Long
 
 With WSh.Cells
  On Error Resume Next
  LewaKolumna = .Find("?", , xlValues, xlPart, xlByColumns, xlNext).Column
  On Error GoTo 0
  If LewaKolumna < 1 Then Exit Function
  GornyWiersz = .Find("?", , xlValues, xlPart, xlByRows, xlNext).Row
  PrawaKolumna = .Find("?", .Cells(1, 1), xlValues, xlPart, xlByColumns, xlPrevious).Column
  DolnyWiersz = .Find("?", .Cells(1, 1), xlValues, xlPart, xlByRows, xlPrevious).Row
  ObszarDanych = .Range(.Cells(GornyWiersz, LewaKolumna), .Cells(DolnyWiersz, PrawaKolumna)).Address(False, False, xlA1, , .Cells(GornyWiersz, LewaKolumna))

' ObszarDanych = .Range(.Cells(GornyWiersz, LewaKolumna), .Cells(DolnyWiersz, PrawaKolumna)).Offset(-GornyWiersz + 1, -LewaKolumna + 1).Address(False, False, xlA1, , .Cells(GornyWiersz, LewaKolumna))
  
 End With

End Function

'turbo ================================================================================================

Sub testTrubo()
 Debug.Print KomorkiZBledamiAdresyTurbo(ThisWorkbook.Sheets("test"))
End Sub

Function KomorkiZBledamiAdresyTurbo(WSh As Worksheet) As String
 Dim DataRngAdr, tmpWb As Workbook, oldCalc, oldScrUpd, pocz, TmpSh As Worksheet
 
 MsgBox "wersja robocza nie obsługuje błędów"
 Exit Sub
 
 pocz = Now
 DataRngAdr = ObszarDanych(WSh)
 If Len(DataRngAdr) < 1 Then Exit Function
 If Not SaKomorkiZBledami(WSh) Then Exit Function
  
  Set TmpSh = WSh.Parent.Sheets.Add
  ttt = WSh.Range(DataRngAdr)
  TmpSh.Cells.Resize(UBound(ttt, 1), UBound(ttt, 2)) = ttt
  KomorkiZBledamiAdresyTurbo = KomorkiZbledami(TmpSh)
  
  Application.DisplayAlerts = False
  TmpSh.Delete
  Application.DisplayAlerts = True
  
  Debug.Print "turbo 1"; CDate(Now - pocz)
End Function

'Find ================================================================================================

Sub szukaj()
Dim fndcel As Range, ErrArr, ele, pocz, DataRngAdr, dtrng As Range, firstAddress
 MsgBox "wersja robocza nie obsługuje błędów"
 Exit Sub
 ErrArr = Array("#DIV/0!", "#N/A", "#NAME?", "#NULL!", "#NUM!", "#REF!", "#VALUE!")
 pocz = Now
 DataRngAdr = ObszarDanych(ActiveSheet)
 If Len(DataRngAdr) < 1 Then Exit Sub
 Set dtrng = Range(DataRngAdr)
 
 For Each ele In ErrArr
  Set fndcel = dtrng.Find(ele, , xlValues, xlWhole)
 
  If Not fndcel Is Nothing Then
   firstAddress = fndcel.Address
   Do
     If IsError(fndcel.Value) Then Debug.Print fndcel.Address; " "; ele
     Set fndcel = dtrng.FindNext(fndcel)
   Loop While Not fndcel Is Nothing And fndcel.Address <> firstAddress
 End If
 Next
 Debug.Print "find "; CDate(Now - pocz)
End Sub

napisał: LAnd
postów: 107


umieszczony:
27 czerwca 2007
19:00

edytowany:
27 czerwca 2007
19:04

  
owocna współpraca wersję turbo opublikuję po testach z Find

dzieki przykładom wyszło mi że wartość szukana w VBA dla błędu to jego angielska wyświetlana nazwa co wymaga wykonania sprawdzen dla kilku wartości



With objWSh

LastRow = .Cells.Find(What:="*", After:=[A1], _
                                  SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row


program nie zgłosił błędu pomimi że był aktywny o nazwie "Arkusz2" a nie "test" , przypadkowo
napisał: jalamas
postów: 316


umieszczony:
27 czerwca 2007
17:55

  
Nie do pogardzenia, prawda.
napisał: r_c
postów: 38


umieszczony:
27 czerwca 2007
13:11

  
Wydaje się, że nie do pogardzenia jest przetworzenie zawartości arkusza przy użyciu dwuwymiarowej tablicy typu Variant:
- wczytanie zawartości arkusza odbywa się prawie natychmiast;
- odczyt tablicy jest również szybki;
- na podstawie indeksów tablicy b.łatwo jest ustalić adres komórki.
odczyt:
If IsError(TABLICA(WIERSZ, KOLUMNA)) Then
      MsgBox CStr(Cells(WIERSZ, KOLUMNA).Value) & " - " & Cells(WIERSZ, KOLUMNA).Address
End If


lub
If Cstr(TABLICA(WIERSZ, KOLUMNA))="Error 2029" Then
      MsgBox "Błąd " & Cells(WIERSZ, KOLUMNA).Address
End If


lub użycie operatora Like i maski znaków lub .... .
Adresowanie dla początku zakresu wg zasady: WIERSZ + (nr wiersza komórki-1), a KOLUMNA + (nr kolumny komórki -1).
pzdr r_c
napisał: LAnd
postów: 107


umieszczony:
27 czerwca 2007
08:31

  
ponieważ SpecialCells działają na arkuszu nie zablokowanym to

1. sprawdzić czy są błędy , będzie szybko szybko
2, utworzyć nowy arkusz - dość szybko
3. wykonać kopię danych do nowego arkusza - trzeba zmierzyć czas
4. da się na nim wykonać SpecialCells i zapamiętać wynik - będzie szybko
5. usunąć nowy arkusz - będzie szybko

teraz sprawdzam czy ta procedura będzie szybsza od iteracyjnego wyszukiania błędu
napisał: jalamas
postów: 316


umieszczony:
26 czerwca 2007
21:12

  
Akurat #NAZWA?, przypuszczam:
Set TmpCell = .Find(What:="#NAME?", After:=komorka_poczatkowa, LookIn:=xlFormulas, _
                            LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
                            MatchCase:=True, SearchFormat:=False)


ale nie tędy droga.... przy innych błędach.
Jest to w zacytowanej procedurze w moim poprzednim poście Case xlErrName.
Jeśli Ci zależy na tym tylko warunku, możesz "rozdzielić" lub wyeliminować przypadki w Case.
Zatem może inaczej, powiedz co w moim przykładzie nie spełnia Twoich wymagań, czego ja nie zauważyłam.
Nie denerwuj się Andrzejku, na pewno problem jakoś da się rozwiązać, ja zapewne nie do końca rozumiem Twojego pytania
Nie upierałabym się przy Find.
napisał: LAnd
postów: 107


umieszczony:
26 czerwca 2007
10:10

edytowany:
27 czerwca 2007
07:21

  
zjadłem na początku "jak"

w.dzięki za zainteresowanie

sprawa dotyczy importu przez sieć danych pomiarowych
zdarza się że zaczytane wartości do komórek sforamtownych ogólnie dla Excela są podobne do formuł i wtedy błąd #NAZWA?

Jak te cholery zlokalizować na zabezpieczonym arkuszu
najlepiej Find(??????,,????,???,) ale jaki argument lub argumenty użyć
w sieci na razie nie znalazłem
Pzdrw


na odblokowany rzeczywiście można


Function KomorkiZbledami(WSh As Worksheet) As String
 Dim RetVal As String
  On Error Resume Next
   RetVal = WSh.Cells.SpecialCells(xlCellTypeConstants, xlErrors).Address
'poprawka 2007-06-27 bo jak nie znajdzie stałych błędów to wynik zaczynałby się od przecinka
' RetVal = RetVal & "," & WSh.Cells.SpecialCells(xlCellTypeFormulas, xlErrors).addres
   RetVal = RetVal & Iif(Len(RetVal)>0 , "," , "") & WSh.Cells.SpecialCells(xlCellTypeFormulas, xlErrors).addres
  On Error GoTo 0
 KomorkiZbledami = RetVal
End Function

napisał: jalamas
postów: 316


umieszczony:
26 czerwca 2007
07:54

  
Nie do końca rozumiem pytanie, nie wiem czy w jest to pytanie, czy komuś odpowiadasz ?
Jeżeli to jest pytanie, rozumiem, że bez zdejmowania ochrony, bo też tego nie zaznaczyłeś ?
To może tak:

Sub Test()
Dim lngRes As Long
    lngRes = CountIsError(ThisWorkbook.Worksheets("test"))
    MsgBox lngRes
End Sub

Public Function CountIsError(objWSh As Worksheet) As Long
    On Error GoTo CountIsError_Error
' jezeli tylko sprawdzic czy sa bledy po 1-szym mozna zakonczyc

    Dim LastCol As Long
    Dim LastRow As Long
    Dim TmpCell As Range
    Dim Rng As Range
    Dim iErr As Long
    With objWSh
        If Application.WorksheetFunction.CountA(.Cells) > 0 Then
            LastRow = .Cells.Find(What:="*", After:=[A1], _
                                  SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
            LastCol = .Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByColumns, _
                                  SearchDirection:=xlPrevious).Column
            Set Rng = .Cells(1, 1).Resize(RowSize:=LastRow, ColumnSize:=LastCol)
        Else
            Exit Function
        End If
    End With
    With Rng
        For Each TmpCell In .Cells
            If IsError(TmpCell.Value) Then
                ' nie wiem czy ten Case jest potrzebny zapytaj Rysia
                ' chyba wystarczy samo: iErr = iErr + 1
                Select Case CLng(TmpCell.Value)
                    Case xlErrDiv0, xlErrNA, xlErrName, xlErrNull, _
                         xlErrNum, xlErrRef, xlErrValue
                        iErr = iErr + 1
                    Case Else
                        MsgBox "????? "
                End Select
            End If
        Next
    End With

    CountIsError = iErr

CountIsError_Exit:
    On Error Resume Next
    Set TmpCell = Nothing: Set Rng = Nothing
    Exit Function
CountIsError_Error:
    MsgBox "Błąd : ( " & Err.Number & " ) " & Err.Description & vbCrLf & _
           "Procedura : " & "CountIsError", vbExclamation
    Resume CountIsError_Exit
End Function


Bo jesli można wziąć pod uwagę zdjęcie ochrony, to można od razu wyznaczyć unię komórek z błędami ?
Info:
Na stronie
http://support.microsoft.com/kb/146864
punkt: Using Built-In Error Values
Rozważania o Last Cell itd&#8230; tutaj:
http://www.ozgrid.com/VBA/ExcelRanges.htm
http://microsoft-personal-applications.hostweb.com/TopicMessages/microsoft.public.excel.worksheet.functions/1984111/2/Default.aspx

P.S.
Cytat:
Application.worksheet.function
-- > Application.WorksheetFunction
napisał: LAnd
postów: 107


umieszczony:
26 czerwca 2007
01:48

  
jakie argumenty do

cells.find(????,,xlvalues,xlwhole)


lub

application.worksheet.function.countif(cells,?????)



moje :

Function SaKomorkiZBledami() as boolean
Dim Blad
set Blad=Nothing
on error resume next
 Blad=application.worksheet.function.sum(cells)
on error goto 0

SaKomorkiZBledami=isobject(Blad)

end function



<-wstecz  1  dalej->
wszystkich stron: 1


Sortuj posty: z