ID tematu: 70593
 |
Fragment kodu nie wykonuje się w losowych (?) przypadkach. |
Autor |
Wiadomość |
wczesny
Stały bywalec Excelforum

Wersja: Win Office 2016
Pomógł: 34 razy Posty: 302
|
Wysłany: 08-04-2021, 14:30 Fragment kodu nie wykonuje się w losowych (?) przypadkach.
|
|
|
Kod: |
Function Utworz_tablice_rachunek(podwojnyrachunek As Boolean) 'dodaje to tablicy pozycje z Facon i warunlkami platnosci, zapisuje do arkusza
10 On Error GoTo Utworz_tablice_rachunek_Error
20 Dim wrk As Worksheet: Set wrk = Worksheets("Rachunki_Wplaty")
30 Dim wrk1 As Worksheet: Set wrk1 = Worksheets("Rachunki")
Dim lrow As Long
Dim i As Long, j As Long, k As Long, y As Long
Dim facon As Double, augewicht As Double, terminfacon As Double, autermin As Double, skonto As Double, kursau As Variant
Dim ary()
Dim tempary()
Dim iloscklient As Double
Dim kwotaF As Double
Dim kwotaA As Double
Dim opakowania As Double
40 With Me.lstboxRachunek
50 For i = 0 To .ListCount - 1
60 If .Selected(i) Then
70 ReDim Preserve ary(0 To 18, 0 To j)
80 ary(0, j) = CLng(Date)
90 ary(1, j) = Nrrachunku
100 For k = 2 To 11
110 ary(k, j) = .List(i, k - 2)
120 Next
'ilosczamowiona = ary(9, j)
130 iloscklient = ary(11, j)
'nrartykulu = ary(8, j)
140 tempary = Znajdz_cene(ary(9, j), ary(11, j), ary(8, j)) 'call sprawdz cene i reszte warunkow
150 If podwojnyrachunek Then
160 facon = tempary(0)
170 augewicht = 0
180 terminfacon = tempary(3)
190 autermin = 0
200 skonto = tempary(5)
210 kursau = 0
220 Else
230 facon = tempary(0)
240 augewicht = tempary(1)
250 terminfacon = tempary(3)
260 autermin = tempary(4)
270 skonto = tempary(5)
280 kursau = Me.txtAu.Value
290 End If
300 ary(12, j) = facon 'facon
310 ary(13, j) = augewicht 'augewicht
320 If InStr(.List(i, 5), "Au") > 0 Then 'kurs Au
330 ary(14, j) = kursau
340 Else
350 ary(14, j) = 0
360 End If
370 ary(15, j) = tempary(6) 'mime galvanik
380 ary(16, j) = terminfacon 'terminfacon
390 ary(17, j) = autermin 'autermin
400 ary(18, j) = skonto 'skonto
410 kwotaF = kwotaF + Round(iloscklient * facon / 1000 + tempary(6), 2)
420 kwotaA = kwotaA + Round((iloscklient * augewicht / 1000) * ary(14, j), 2)
430 j = j + 1
440 End If
450 Next
460 End With
470 If tempary(7) = "WDT" Then Me.OptWDT = True 'przelacza opcje na WDT
480 If tempary(7) = "RC" Then Me.OptResCharge = True 'przelacza opcje na RC
490 With wrk1 'dodaje watrosci do bazy rachunków
500 If Not IsEmpty(.Range("A2").Value) Then
510 .Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary)
520 Else
530 .Cells(Rows.Count, "A").End(xlUp).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary)
540 End If
550 End With
560 With Me.lstboxOpakowania 'koszty opakowan
570 If .ListCount > 0 Then
580 For i = 0 To .ListCount - 1
590 opakowania = opakowania + (.List(i, 0) * .List(i, 2))
600 Next
610 End If
620 End With
630 With wrk 'wplaty
640 If Not IsEmpty(.Range("A2").Value) Then
650 lrow = .Cells(Rows.Count, "A").End(xlUp).Row + 1
660 Else
670 lrow = .Cells(Rows.Count, "A").End(xlUp).Row
680 End If
690 .Cells(lrow, 1) = Date
700 .Cells(lrow, 1).NumberFormat = "dd.mm.yyyy"
710 .Cells(lrow, 2) = Nrrachunku
720 .Cells(lrow, 3) = Nazwaklienta
730 .Cells(lrow, 4) = terminfacon
740 .Cells(lrow, 5) = autermin
750 .Cells(lrow, 6) = skonto
760 .Cells(lrow, 7) = kwotaF
770 .Cells(lrow, 8) = kwotaA
780 .Cells(lrow, 9) = opakowania + Val(Replace(Me.txtTransport.Value, ",", "."))
790 End With
800 Call Dodaj_nrrachunku_do_listow(ary(2, 0)) 'dodaje numer rachunku w tabeli listow przewozowych
810 Utworz_tablice_rachunek = ary
820 On Error GoTo 0
830 Exit Function
Utworz_tablice_rachunek_Error:
840 BLAD = "Error " & Err.Number & " (" & Err.Description & ") in procedure Utworz_tablice_rachunek, line " & Erl & "."
850 Logger "Error", BLAD, Err.Description
860 MsgBox "Wystapil blad."
End Function
|
Cześć,
mam problem z powyższym kodem tj od 490 do 550 oraz 630 do 790.
Występują przypadki w których tablica oraz dane nie są dodane do arkuszy . Niestety error logger nic nie wykrywa.
Makro jest uruchamiane w "głównym" skoroszycie. W dalszej części kodu otwierany jest inny skoroszyt i te same dane są wklejane. Tam wszystko jest ok.
Jest możliwość, że transpose coś gubi lub użytkownik w czasie wykonywania makra dezaktywuje skoroszyt?
Z góry dzięki za pomysły. |
|
|
 | ID posta:
403298
|
|
|
 |
|
|
|
Rafał B.
Stały bywalec Excelforum


Wersja: Win Office 2016
Pomógł: 40 razy Posty: 283
|
Wysłany: 08-04-2021, 15:42
|
|
|
Po prostu napisz króciutką funkcję sparwdzającą czy coś tam zostało wklejone (może nawet VBA.Len na pierwszej komórce wystarczy) i dodaj ją tymczasowo do kodu wraz z jakimś przerywnikiem (Msgbox lub Stop) na zasadzie:
Kod: | 490 With wrk1 'dodaje watrosci do bazy rachunków
500 If Not IsEmpty(.Range("A2").Value) Then
510 .Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary)
520 Else
530 .Cells(Rows.Count, "A").End(xlUp).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary)
540 End If
550 End With
' rng np. pierwsza komorka
' moze wystarczy nawet If VBA.Len() = 0
If NothingPasted(rng) Then Stop
(...)
|
Wtedy na spokojnie w Locals dojdziesz skąd błąd. Transpose gubi powyżej 65k z groszami (słynny wątek Artika na tym forum), wywala błąd przy transpozycji w przypadku zawartości z długimi stringami. Ale w pierwszym przypadku coś jednak wkleiłoby (tylko obcięło dane, a w drugim wywaliło błąd, więc to nie jest najlepszy trop raczej).
PS.
Takie konstrukcje są mało czytelne:
Kod: | .Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary) |
Rozważyłbym dołożenie tam zmiennych, a nie kilka operacji w jednej linijce, łatwiej też śledzić wartość zmiennych przy debugowaniu; ciężko sobie wyobrazić jak ten Range wygląda |
_________________ Jest niemal niemożliwe nauczenie dobrego programowania uczniów, którzy byli narażeni na kontakt z BASIC: jako potencjalni programiści są okaleczeni, bez nadziei na poprawę. (Edsger Dijkstra, pionier informatyki).
Po części dotyczy również VBA. |
|
|
 | ID posta:
403300
|
|
|
 |
|
|
wczesny
Stały bywalec Excelforum

Wersja: Win Office 2016
Pomógł: 34 razy Posty: 302
|
Wysłany: 08-04-2021, 16:04
|
|
|
Problemem jest, że ten plik używa koleżanka i mam informacje typu "Znowu nie zapisało jednego, ale poprzednie / następne są ok :)", do tego nie zawsze mogę podejść do jej komputera.
Dlatego zastanawiam się w jakich sytuacjach może wystąpić problem.
Dzisiaj to jeszcze raz kilka razy debugowałem i nie mam pojęcia, co może sprawiać problemy. |
|
|
 | ID posta:
403302
|
|
|
 |
|
|
Rafał B.
Stały bywalec Excelforum


Wersja: Win Office 2016
Pomógł: 40 razy Posty: 283
|
Wysłany: 08-04-2021, 16:11
|
|
|
Kod: | Set wrk = Worksheets("Rachunki_Wplaty") |
Czemu brakuje kwalifikacji? Przeoczyłem to na początku, a w przypadku więcej niż jednego skoroszytu jednocześnie to niewybaczalny błąd (koniecznie popraw to w całym kodzie, nie tylko przytoczonym). Sam dobrze zdiagnozowałeś o tej dezaktywacji. Jeśli rezultat ma być w bieżącym "głównym" skoroszycie, to dodaj ThisWorkbook:
Kod: | Set wrk = ThisWorkbook.Sheets("Rachunki_Wplaty") |
Jeśli w tym drugim skoroszycie, to musisz do niego jakiś uchwyt mieć. Możesz iterować po kolekcji Application.Workbooks, użyć GetObject etc.
Ale najbezpieczniej - o ile to możliwe- daj opcję otwierania tego drugiego pliku ze swojego głównego. Wówczas wykluczysz kłopotliwą możliwość innej instancji (chyba, że ograniczamy się do Windows, to API pomoże wylistować wszystkie instancje, w natywnym VBA chyba takiej możliwości nie ma poza "zgadywankami").
PS
W wolnej chwili poczytaj o Model-View-Controller separując warstwę logiki biznesowej od widoku (tutaj userform), bo ten userform zawiera o wiele za dużo logiki niezwiązanej z nim samym. Starasz się pisać ładnie i bardzo dobrze, ale nadal jest tu bałagan. A zastosowanie jakiegoś wzorca projektowego pomoże Ci w przyszłości go uniknąć. Pozdrawiam. |
_________________ Jest niemal niemożliwe nauczenie dobrego programowania uczniów, którzy byli narażeni na kontakt z BASIC: jako potencjalni programiści są okaleczeni, bez nadziei na poprawę. (Edsger Dijkstra, pionier informatyki).
Po części dotyczy również VBA. |
|
|
 | ID posta:
403303
|
|
|
 |
|
|
wczesny
Stały bywalec Excelforum

Wersja: Win Office 2016
Pomógł: 34 razy Posty: 302
|
Wysłany: 08-04-2021, 17:19
|
|
|
Dzięki za rady.
Poprawię kod i zobaczymy czy tylko o to chodziło.
Trochę się dziwię, że nie wywalało błędu. |
|
 | ID posta:
403304
|
|
|
 |
|
|
ąćęłńóś
Excel Expert

Pomógł: 327 razy Posty: 1615
|
Wysłany: 08-04-2021, 20:18
|
|
|
wczesny napisał/a: | Poprawię kod |
Powinieneś ...
Pewnie to tylko moje zdanie w "tym temacie", ale jak dla mnie to "funkcja" 'Utworz_tablice_rachunek' wcale nie jest funkcją, przypomina raczej zwykłą podprocedurę 'Sub'.
Z poziomu tej "funkcji" wywołujesz jakieś inne "działania":
Kod: | tempary = Znajdz_cene(ary(9, j), ary(11, j), ary(8, j)) 'call sprawdz cene i reszte warunkow
'...
Call Dodaj_nrrachunku_do_listow(ary(2, 0)) 'dodaje numer rachunku w tabeli listow przewozowych
'...
Logger "Error", BLAD, Err.Description
MsgBox "Wystapil blad." |
odnoszące się w tle do innych funkcji/"funkcji" i/lub podprocedur, i którą to "funkcję główną" na końcu okraszasz jeszcze taką "egzotyką" jak 'MsgBox' w funkcji ... : / ... co najmniej dziwne ... nie twierdzę, że niedopuszczalne, bo z tego co widzę, to owa "dopuszczalność" ma dla każdego zupełnie inne znaczenie, ale jest to "dziwne" ...
Dodatkowo wykonujesz w funkcji działania "wyjątkowo aktywne", czyli manipulacje na komórkach arkusza - wstawiające określone dane do komórek, które nie są adresatem wyniku funkcji - według mnie (?) ... mojego nastawienia do "instytucji" funkcji jako takiej (?) ... jest to mało "funkcyjne" i wyjątkowo "proceduralne", w sensie wykonywania działań w ramach 'Sub' - podprocedur.
Może jestem "konserwa niereformowalna", ale dla mnie funkcja jest "ciałem" wyjątkowo "biernym", jeśli chodzi o operacje, które wykonuje, jest "obliczeniowa".
Dalej, ogólna klauzula 'On Error GoTo' - jest to wyjątkowe "olanie" tego, co właściwie się wewnątrz tej "funkcji" dzieje i z czym sobie "nie jesteśmy w stanie poradzić" - można by bowiem zadać sobie pytanie, co się właściwie tu dzieje, jeśli z jakimś "błędem" powrócą do kodu "funkcji głównej" owe odwołania do zewnętrznych funkcji/podprocedur, w jakim zakresie, to co zwracają, nie pasuje do oczekiwanego jej działania, wyniku ?
Mamy tu zatem taką sytuację, że funkcja, która w wyniku swojego działania powinna, poprzez swoją "nazwę", zwrócić jakąś "wartość", w przypadku błędu nie zwraca nic, tylko 'MsgBox'.
Tak więc, jak dla mnie - co zaznaczam - przypomina to raczej czekoladowy przekładaniec, niż funkcję wykonującą określone "obliczenia", czy to dla podprocedury, czy to bezpośrednio do komórki(-ek) (UDF). |
|
 | ID posta:
403314
|
|
|
 |
|
|
wczesny
Stały bywalec Excelforum

Wersja: Win Office 2016
Pomógł: 34 razy Posty: 302
|
Wysłany: 08-04-2021, 20:55
|
|
|
To jest mój pierwszy kontakt z programowaniem, a mam już trochę lat na karku, także jak coś działało, to nie zastanawiałem się za bardzo dlaczego, tylko się z tego cieszyłem :)
Rzeczywiście ten projekt jest chaotyczny ze względu na brak wiedzy oraz planowania przed jego tworzeniem.
Nie wiem za bardzo dlaczego czepiasz się zastosowania funkcji lub procedury. Przecież kod nie wykonuje się inaczej, tylko jest ewentualnie zwracana jakaś wartość.
Obsługa błędów była stworzona do wychwytywania miejsca błędu tj. w pliku tekstowym zapisywana jest nazwa procedury, data, jaki błąd oraz nr linii. |
|
 | ID posta:
403315
|
|
|
 |
|
|
ąćęłńóś
Excel Expert

Pomógł: 327 razy Posty: 1615
|
Wysłany: 09-04-2021, 00:29
|
|
|
To nie kwestia czepiania się ... to moje 3 grosze w temacie, na które nie musisz zwracać uwagi.
Przyjrzyj się temu kodowi uważnie i spróbuj krok po kroku prześledzić go pod kątem:
- dziwnego miejsca występowania argumentu decyzyjnego funkcji (argument 'podwojnyrachunek') - nie "na początku", w miejscu gdzie, wydawałoby się, decydowałby o kierunku przeprowadzanych działań, ale gdzieś w głębi - dlaczego tak jest (?), co o tym decyduje, jaka specyfika działań, że akurat tam, a nie na początku (?),
- sztywności powiązania z 'ListBox'ami:
- - i tego, że sporo "ważnych rzeczy" dzieje się w obrębie tych obiektów, które cały czas trzymają w pamięci jakieś swoje odwołania do niej i jedynie święty Lelum Polelum wie jak to wpływa na działanie innych "konstrukcji", które w międzyczasie coś w tej pamięci grzebią, będąc "wpiętymi" w te odwołania, a jednocześnie będąc odsyłanymi do innych podprocedur/funkcji
- miejsc, w których jest "wybijany z rytmu" jakimiś "przerywnikami":
- - co dzieje się, gdy z jakichś względów, po przesłaniu "działań" do procedur zewnętrznych, powróci on do "głównego nurtu" z "nieakceptowalnymi" wartościami,
- - gdzie obsługa takich niechcianych danych (?)
- - co komukolwiek daje informacja z pliku logu o błędzie ('Err.Description') typu "Object required", itp. (?) i linii jego wystąpienia, skoro i tak nie można odtworzyć sytuacji, która go wywołała ?
- itd.
Według mnie - znowu zaznaczam, według mnie - to nie funkcja tylko podprocedura, poprzeplatana zagnieżdżonymi odwołaniami do kolejnych podprocedur oraz być może funkcji. Takie kolejne zagnieżdżanie nieszczególnie służy prawidłowości wykonywania kodu, chociażby ze względu na "ByRef" i "ByVal" przekazywanych argumentów (jakieś informacje o tym znajdziesz w pomocy podręcznej, jak również na forum).
Według mnie powinieneś porozdzielać to na funkcjonalne etapy, z jednej strony nie objęte "wspólnym ramieniem ListBox'ów" ('lstboxRachunek'), a z drugiej uniezależnione od zagnieżdżeń ('Znajdz_cene' i 'Dodaj_nrrachunku_do_listow'). Konstrukcja "With ... End With", też nie we wszystkich sytuacjach się sprawdzi, czasami (a może nawet) lepsze są przypisania 'Set'.
Jak to zrobić, porozdzielać ? Nie wiem, sam twój kod nie daje ogólnego wglądu w proces i kolejność w jakiej się to ma odbywać - brak przykładu, choćby z grubsza symulującego prawdziwe zagadnienie.
Ps: Wszystko dzieje się w obrębie formatki 'UserForm', a więc dochodzą tu również jej obciążenia-uwarunkowania, wynikające chociażby z kolejności obsługiwanych w niej zdarzeń, robi się z tego cały łańcuszek - łatwo to sprawdzić tworząc formatkę testową z jakimś obiektem i jego obsługiwanymi zdarzeniami, można wtedy na własnej skórze przekonać się jak taka formatka "hałasuje" okropnie, skacząc po wielokroć po tych samych zdarzeniach w danym obiekcie - to też trzeba uwzględnić. |
|
 | ID posta:
403323
|
|
|
 |
|
|
wczesny
Stały bywalec Excelforum

Wersja: Win Office 2016
Pomógł: 34 razy Posty: 302
|
Wysłany: 09-04-2021, 09:03
|
|
|
Postaram się usunąć dane wrażliwe i załączę cały plik.
Generalnie jeżeli chodzi o poprawność danych, to wszystko jest sprawdzane w podprocedurach procedury głównej, czyli jeżeli coś nie zgadza kod, nie ma prawa dojść do tego momentu. |
|
 | ID posta:
403327
|
|
|
 |
|
|
|
Nie możesz pisać nowych tematów Nie możesz odpowiadać w tematach Nie możesz zmieniać swoich postów Nie możesz usuwać swoich postów Nie możesz głosować w ankietach Nie możesz załączać plików na tym forum Możesz ściągać załączniki na tym forum
|
Dodaj temat do Ulubionych Wersja do druku
|
 |
Strona używa plików cookies.
Kliknij tutaj, żeby dowiedzieć się jaki jest cel używania cookies oraz jak zmienić ustawienia cookie w przeglądarce.
Korzystając ze strony użytkownik wyraża zgodę na używanie plików cookies, zgodnie z bieżącymi ustawieniami przeglądarki.
Sprawdź, w jaki sposób przetwarzamy dane osobowe
|