logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

VBA makro do tworzenia arkuszy o nazwach pobieranych z komórek

darkstar666 21 Wrz 2022 15:27 1956 35
Najlepsze odpowiedzi

Jak w VBA utworzyć tyle nowych arkuszy, ile jest wypełnionych komórek w zakresie, i nadać im nazwy pobrane kolejno z tych komórek?

Makro powinno przejść po kolejnych niepustych komórkach z nazwami arkuszy, utworzyć dla każdej z nich nowy arkusz i nadać mu nazwę pobraną z danej komórki [#20203268] W zaproponowanym przykładzie nazwy są czytane z arkusza o nazwie kodowej Arkusz1 z kolumny B, od komórki B5 w dół, a pusta komórka kończy listę danych [#20203268] Nowe arkusze są dodawane za ostatnim istniejącym arkuszem [#20203268] Po zakończeniu procedury kod wraca do Arkusz1 [#20203268]
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA
  • #1 20201022
    darkstar666
    Poziom 5  
    Posty: 22
    Witam wszystkich. Aktualnie pracuję nad dużym plikiem analitycznym zawierającym trochę małych makr. W tej chwili mam problem z makrem do tworzenia arkuszy o nazwach pobieranych z zakresu komórek. Zależy mi na tym, aby makro sprawdzało, ile jest wypełnionych pól w dedykowanej tabeli (zakresie) przeznaczonym do wpisywania kodów przez użytkownika, a następnie tworzyło tyle nowych arkuszy o nazwach pobieranych z kolejnych komórek, ile jest wpisanych kodów. Zatrzymałem się na tym etapie:

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod




    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    Ktoś coś?
  • REKLAMA
  • Pomocny post
    #2 20203268
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Powinieneś załączyć przykładowy plik Excela, bo za dużo jest niejasności w tym, co napisałeś.
    Przykładowy kod, który działa wg Twojego opisu:
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod

    Przyjęte założenia:
    1) Komórki z nazwami arkuszy do wstawienia znajdują się w arkuszu o nazwie kodowej Arkusz1 w kolumnie B zaczynając od komórki B5 w dół. Założyłem, że wszystkie kolejne komórki od B5 są wypełnione. Pusta komórka oznacza koniec danych.
    2) Nowe arkusze są dodawane za ostatnim istniejącym arkuszem.
    3) Po dodaniu nowych arkuszy kod wraca do Arkusza1.

    Z Twojego opisu nie wynika, co ma być dalej. Czy po zmianie danych w kolumnie B Arkusza1 mają być dodawane kolejne nowe arkusze, czy te wcześniej dodane mają być usunięte i dopiero dodane nowe.
  • #3 20213048
    darkstar666
    Poziom 5  
    Posty: 22
    Dziękuję, po lekkiej modyfikacji i dopasowaniu kodu wszystko działa tak jak powinno.

    Moje kolejne zmartwienie to przepisanie funkcji "wyszukaj.pionowo" na kod VBA:

    =WYSZUKAJ.PIONOWO('Arkusz2'!A43;'Arkusz2'!A:E;5;0)

    Mam takie coś:

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    To sztywna formuła, która odwołuje się do konkretnego arkusza i konkretnej komórki i kolumn. Jak zmodyfikować formułę w VBA, żeby:
    1. Zamiast arkusza "Arkusz2" formuła szukała arkusza o nazwie pobieranej z komórki (np. B6) z aktywnego arkusza?
    2. Przy zachowaniu funkcjonalności z pkt.1 szukała w tym arkuszu komórki zawierającej określony tekst (a nie, jak wyżej zawartość komórki A43) i na tej podstawie wyrzucała wynik.

    Podczas poszukiwań składni tej funkcji natrafiłem na różne jej sformułowania. Jaka jest różnica pomiędzy: ActiveCell.FormulaR1C1 / ActiveCell.Formula / ActiveCell.Function / Application.WorksheetFunction / WorksheetFunction, ponieważ widzę różną składnię tego samego polecenia i szczerze powiedziawszy ciężko jest dostrzec różnice i zastosowanie.
  • Pomocny post
    #4 20213157
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Ad 1. Tu należy zwrócić uwagę, że każdy arkusz ma w VBA dwie nazwy, tzw. nazwę "zakładkową" - widoczną na zakładce arkusza i nazwę kodową - dostępną tylko w VBA. Te nazwy są początkowo identyczne, ale użytkownik może je zmieniać niezależnie, więc mogą później się różnić. Jeśli piszemy odwołanie:
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod
    to wykorzystujemy nazwę zakładkową arkusza, a jeżeli napiszemy:
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod
    to używamy nazwy kodowej.

    Wracając do treści pytania, odwołanie może wyglądać tak:
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod
    Komórka B6 musi zawierać nazwę zakładkową arkusza, z którego chcemy czytać dane.

    Ad 2. Należy podać szukany tekst w cudzysłowie:
    Kod: Text
    Zaloguj się, aby zobaczyć kod


    Ad 3.
    darkstar666 napisał:
    Jaka jest różnica pomiędzy: ActiveCell.FormulaR1C1 / ActiveCell.Formula / ActiveCell.Function / Application.WorksheetFunction / WorksheetFunction

    ActiveCell.FormulaR1C1 oznacza, że formuła będzie w wersji angielskiej, a odwołania w niej będą w stylu R1C1
    ActiveCell.Formula oznacza, że formuła będzie w wersji angielskiej, a odwołania w niej będą w stylu A1
    ActiveCell.Function - nie ma takiej składni
    Application.WorksheetFunction.angielska_nazwa_funkcji i WorksheetFunction.angielska_nazwa_funkcji oznaczają to samo, natomiast
    Application.angielska_nazwa_funkcji jest wywołaniem "w starym stylu" i w szczegółach różni się od poprzedniego (inna obsługa błędów, obsługa składni rozszerzonej, ale za to jest nieco wolniejsza).

    Nota bene ten kod, który pokazałeś to jest pomieszanie z poplątaniem.
    Funkcje arkuszowe można wywoływać w VBA w ten sposób, że obliczenia wykonuje VBA i do komórki trafia tylko wynik. Wtedy piszemy np.
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod
    Używamy tu odwołań do obiektów lub ich wartości.
    Inny sposób, to wstawienie formuły do komórki arkusza, i dopiero ta formuła przy przeliczeniu arkusza zwróci wynik. Wtedy używamy właściwości Formula lub analogicznej:
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod
    Tu zapis jest jak w angielskim Excelu.
    Użycie Formula zamiast Value w pierwszej wersji nie jest błędem, ale niepotrzebnie zaciemnia zapis i wymusza dodatkowe działanie.
  • REKLAMA
  • #5 20223779
    darkstar666
    Poziom 5  
    Posty: 22
    Dziekuję za zwrócenie uwagi na róznicę w zapisuwaniu nazw arkuszy.

    Odnosnie pkt 2 doszedłem do takiego etapu:

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    Wybrałem zapis "AcitiveCell.Value = " zamiast "ActiveCell.Formula = ", ponieważ wyrzuca tylko wynik, a nie wstawia całą funkcję. Z tego poziomu zapisu składnia nie obsłuży poszukiwania komórki po zawartości.

    Kiedy próbuję zastosować wspomnianą zmianę:

    Cytat:

    Ad 2. Należy podać szukany tekst w cudzysłowie:
    "szukana_fraza"


    wyrzuca mi błąd 1004. Próbowałem także z opcją .Value, niestety bezskutecznie. Jak więc zamiast stałej komórki "A43" zapisać poszukiwanie komórki zawierającej określony tekst?
  • Pomocny post
    #6 20223926
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Zdecydowanie łatwiej się porozumieć na bazie załączonego pliku. Widać wtedy różne niuanse, które mogą wydawać się z pozoru nieistotne, a poza tym można przetestować proponowany kod.
    Powinien działać kod:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
    Zakładam, że szukasz dokładnie słów "szukana_fraza" w kolumnie A, a wynik chcesz zwrócić z kolumny E. Użycie .Value czy .Formula po ActiveCell jest bez znaczenia, jeśli wynikiem wyszukiwania jest stała. Zasadne jest użycie .Formula, gdy wynik wyszukiwania jest tekstem jakiejś formuły (w języku angielskim).
  • #7 20225233
    darkstar666
    Poziom 5  
    Posty: 22
    Owszem, jestem tego samego zdania, jednakże wolę zrozumieć kod pisząc go, a nie dostawać wszysko gotowe, stąd moje stopniowe rozwiązywanie problemu. Jeśli jednak plik jest niezbędny, utworzę taki (w tej chwili pracuję na danych, których nie mogę udostepnić).

    Powracając do tematu, jak wspomniałem wcześniej, wybrałem zapis "AcitiveCell.Value = " zamiast "ActiveCell.Formula = ", ponieważ wyrzuca tylko wynik w postaci liczby, a nie wstawia całą funkcję. I teraz porównując zapisy:

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    i
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    już z konkretnymi danymi z arkusza, powstaje problem, ponieważ o ile dla jednej ekstrakcji danych to się sprawdza, o tyle dla sumy kilku danych, których potrzebuję wyszkać, już nie. Czyli jak np:

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    Jak więc wpisać sumy funkcji, używając "Application.WorksheetFunction..."? Suma vlookup'ów: Application.WorksheetFunction.Sum(Application.WorksheetFunction.VLookup() + Application.WorksheetFunction.VLookup() )?

    Widzę też, że tylko dla takiego zapisu funkcji będzie możliwe wyszukiwanie i przyporządkowywanie dynamiczne, czyli zamiast konkretnej nazwy arkusza ("HDK021") będę potrzebował przyporzadkować zmienną z komórki B6, a dla komórki (A43, A50), będę potrzebował wyszukiwania ciągu znaków. Podsumowując, dla każdej wartości z komórki B6, będącej nazwą arkusza, potrzebuję wyciągnąć szukane dane lub sumy szukanych danych :)
  • #8 20225320
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Bez przykładowego pliku traci się zbyt dużo czasu na domysły.
    Ty piszesz, że coś się sprawdza lub nie, a ja mam się domyślać na czym polega problem.
    Jak już pisałem, zapis:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
    zwróci wartość, chociaż użyto właściwości Formula.
    Natomiast zapis:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
    zwróci do komórki formułę, bo po prawej stronie jest tekst formuły. Dopiero ta formuła, po przeliczeniu przez Excela pokaże wartość.

    Suma może być użyta w obu przypadkach, o ile dodajesz liczby. Trudno się domyślić na czym polega problem, bo Twój opis jest bardzo ogólny.

    Gdy sumujesz nie ma potrzeby dublowania funkcji SUM i znaku +.
    Jeśli SUM, to argumenty oddzielamy przecinkami, jeśli używamy + to SUM jest niepotrzebne.
  • #9 20265964
    darkstar666
    Poziom 5  
    Posty: 22
    Ok, jestem po dłuższej przerwie...

    Ogarnąłem temat z funkcją wyszukaj.pionowo z wpisaniem treści formuły do komórki:

    Kod: VBScript
    Zaloguj się, aby zobaczyć kod

    lub
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod

    Mam natomiast problem z wpisaniem składni do funkcji sumowania pionu danych:
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod

    Powyższa składnia wpisuje mi do komórki formułę "=D7/E2". Jak zapisać ten fakt, aby w komórce był tylko wynik pionu danych o adresach komórki od "w, kQy.Column" do "ostw, kQy.Column" (wiersz, kolumna)? Nie przyjmuje mi takich argumentów.
  • #10 20266024
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    darkstar666 napisał:
    Arkusz1.Cells(ostw + 1, kQy.Column).Formula = Application.WorksheetFunction.Sum("=D7/E2")
    Bardzo dziwne rzeczy wypisujesz w tym wyrażeniu.
    1) Jeśli po prawej stronie masz wyrażenie zwracające wartość (WorksheetFunction.Sum), to po lewej stronie powinno być .Value, a nie .Formula.
    Pisałem już o tym, to nie jest formalny błąd, ale zagmatwanie kodu.
    2) Jeśli używasz funkcji Sum, to argumentem musi być zakres komórek (odwołanie), a nie tekst formuły.
    Nigdy w takich okolicznościach nie powinno być cudzysłowów ani znaku = wewnątrz Sum.
    3) Jeśli chcesz sumować zakres komórek, to odwołanie do tego zakresu wewnątrz Sum może wyglądać tak:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    Zakładam, że oznaczenia, których użyłeś są poprawne. Bez przykładowego arkusza nie można tego zweryfikować. Nie wiem co to jest kQy? W każdym razie Range i Cells bez kwalifikatorów odnoszą się do arkusza aktywnego.
  • #11 20267212
    darkstar666
    Poziom 5  
    Posty: 22
    Zadziałała taka składnia, ale po części:
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod

    przy założeniu, że w to pierwszy wiersz, ostw to ostatni wiersz, kQy.Column to numer kolumny ustawionej, aby szukać pionowego zakresu danych.

    Problem polega na tym, że zlicza wszystkie wartości liczbowe w pionie, ale bez ostaniego, czyli przy układzie:
    2
    4
    6
    pod tym podaje wynik 6 (w ułamku sekundy widzę jakąś liczbę dwucyfrową - prawdopodobnie 12 jako sumę powyższych komórek, ale potem zostaje 6). Chodzi ty chyba o to, że chcę podać sumę bezpośrednio pod pionem danych i tą sumę też chyba jakoś bierze do liczenia...
  • #12 20267221
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Czemu nie załączysz przykładowego arkusza?
    Ten kod, który napisałeś ma niewielki sens, bo w pętli powtarzasz ciągle to samo.
    Po lewej stronie masz adres konkretnej jednej komórki, do której trafia wynik. A po prawej stronie zmieniasz zakres sumowania, ale wyniki trafiają i tak do tej samej komórki, więc się nadpisują i otrzymujesz w efekcie wynik ostatniego kroku pętli.
  • #13 20267309
    darkstar666
    Poziom 5  
    Posty: 22
    Wiem, nie mam pomysłu na rozdzielenie tego odwołania cyklicznego :/

    Plik załączony.

    Jaka będzie więc składnia podstawowych funkcji matematycznych w VBA? Tak jak poniżej?

    Suma:
    Arkusz1.Cells(ostw + 1, kQy.Column).Value = Application.WorksheetFunction.Sum(Range(Cells(w, kQy.Column), Cells(ostw, kQy.Column)))

    Różnica:
    ??

    Iloczyn:
    WorksheetFunction.Product(Range(Cells(w, kQy.Column), Cells(ostw, kQy.Column)))

    Iloraz:
    WorksheetFunction.Quotient(Range(Cells(w, kQy.Column), Cells(ostw, kQy.Column)))
  • #14 20267390
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    W sumie nie wiem, czy chcesz mieć w wyniku wartości, czy formuły.
    Zrobiłem oba warianty.
    Pamiętaj, że nie zawsze trzeba i opłaca się używać funkcji. Są też operatory +, -, *, /. Wybór zależy od danych - jeśli dane są liczbowe, to prawie nie ma różnicy. Problemy mogą być przy danych nieregularnych wymieszanych z liczbami (teksty, puste komórki, wartości logiczne itp.).

    Poza tym miałeś pomieszaną kolejność wiersz/kolumna.
    Pamiętaj, że w Excelu tylko przy adresowaniu typu A1 podajemy najpierw kolumnę, a potem wiersz. We wszystkich innych sposobach adresowania jest najpierw wiersz, a potem kolumna. I tego trzeba pilnować, bo Excel nie ma jak się domyślić, co my chcemy.
    Załączniki:
    • Trial1.zip (19.84 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #15 20267428
    darkstar666
    Poziom 5  
    Posty: 22
    Dziękuje, obie wersje przydadzą się w przyszłości. Tutaj chciałem mieć tylko wartości.

    Pytanie dotyczące aktualizacji wyników:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    lub
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    dotyczyło faktu możliwości zmiany wartości danych, aby wynik aktualizował się od razu po zmianie (stąd powyższy znaleziony fragment). Ma to miejsce w tej sytuacji tylko przy opcji wpisania w wyniku formuł (wartości pozostają niezmienne).

    Co to podstawowych funkcji (+, -, *, /), operatory są możliwe do zastosowania przy konkretnych danych, mi zależy aby funkcje zawierały odniesienia dynamiczne, tak jak właśnie poniżej:

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    Czy mój zapis tych podstawowych funkcji jest poprawny?
  • REKLAMA
  • #16 20267599
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Z tą aktualizacją to znowu jakieś nieporozumienie.
    Jeśli dane będą się często zmieniać, ale sposób ich obróbki będzie niezmienny, to należy stosować formuły i przeliczanie automatyczne. Wtedy sam Excel zadba o to, by wszystko było aktualne.
    Jeśli wpisujesz do komórek wartości, to w domyśle te dane nie powinny się zmieniać, albo na tyle rzadko, żeby po zmianie móc ręcznie uruchomić makro.
    Ewentualne rozwiązanie pośrednie, to makro zdarzeniowe wyzwalane automatycznie, gdy jakaś komórka zmienia wartość. Ale należy wtedy określić, które komórki mają być nadzorowane, bo jeśli będziemy reagować na wszystkie zmiany, to arkusz będzie działał powoli, mniej efektywnie niż przy formułach.

    Automatyczne przeliczanie arkusza czy skoroszytu dotyczy tylko formuł, a nie makr, więc jeśli masz makro, które wstawia do komórek wartości stałe, to przeliczanie arkusza tak jak zapisałeś nic tu nie da.

    Poza tym, po co jest to
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
    Po pierwsze, to jest ustawienie domyślne - czy ktoś lub coś Ci to zmienia, że musisz resetować? Po drugie, czy w ogóle korzystasz z tego ustawienia? Robisz jakieś obliczenia iteracyjne?

    Zastosowanie operatorów nie ma nic wspólnego z danymi dynamicznymi. Zarówno operatory jak i funkcje można stosować i do danych statycznych i dynamicznych. Gdy operujemy na pojedynczych wartościach działa to prawie tak samo, tylko inny jest sposób zapisu.
    Natomiast gdy danymi są tablice lub zakresy komórek, to sposób działania operatorów i funkcji jest różny. Poza tym odgrywa rolę również wersja Excela. W najnowszych wersjach 2021 i 365 są tzw. tablice dynamiczne, które pozwalają uzyskiwać tablice wyników z jednej formuły.
  • #17 20286061
    darkstar666
    Poziom 5  
    Posty: 22
    Witam, właśnie taki mam zamianr, aby możliwie jak najwięcej formuł zautomatyzować i uzależnić od wpisywanych danych, aby wszystko automatycznie było przeliczane. Nie chcę też go komplikować, odnośnie tematu z makrem zdarzeniowym, także myslę, że ten poziom automatyzacji obliczeń będzie odpowiedni. Dziękuję także za wspomnienie o tablicach dynamicznych - jest to rewelacyjen rozwiązanie, ale w tej chwili nie znajduje w nim tutaj zastosowania.

    Niemniej jednak mam kolejne tematy, przez które nie mogę się przebić:

    1. Moduł 3 - tworzenie kolumn

    Nie mogę oznaczyć numerów kolumn D i E zmiennymi kWc i kW. W tej chwili są stałe, ale nie zawsze tak będzie, dlatego zależy mi na tym, aby makro szukało nazwy kolumny i na tej podstawie podawało numery kolumn do późniejszych obliczeń.

    Poza tym wydaje mi się, że można skompresować dwa wiersze:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    do jednego:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    ale makro tego nie przyjmuje.



    2. Moduł 4 - kurs euro

    Tu po oznaczeniu numerów kolumn zmiennymi chciałbym uwolnić stałe komórki i je zautomatyzować (E1, E2, E2:E itp) oraz zmienić formułę na taką, która wpisuje od razu wynik przewalutowania.

    Czy czasem także w obu przypadkach ustawienie zmiennych kWc i kW nie powinno być już wpisane w pętli (makro startuje z pierwszego arkusza, a wykonuje te same instrukcje dla pozostałych arkuszy, czy to się nie gryzie?), ponieważ wyrzuca mi różne błędy w takiej sytuacji.
  • #18 20286906
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Koncepcja działania tego kodu jest niejasna.
    W module 3 na początku jest błąd logiczny. Szukasz tekstów "Wartosc calkowita" i "Waluta" w Arkuszu1 (Kalkulacja), gdzie ich nie ma, natomiast są w pozostałych arkuszach, ale tylko chwilowo, bo zaraz zostaną nadpisane.
    Piszesz, poza tym, że chcesz oznaczyć numery kolumn, a tu nazwy kWc i kW odnoszą się do komórek (obiektów) w tym arkuszu, w którym zostaną znalezione.

    Jeśli chcesz używać tych samych adresów w kilku arkuszach, powinieneś operować nie na obiektach komórek, tylko na ich adresach lub numerach kolumn.

    Dalej, połączenie 2 wierszy z pominięciem selekcji jest możliwe i nie wiem, jaki miałeś z tym problem. Jedynie jeśli przypisujesz wartość, a nie formułę, to powinieneś używać właściwości .Value, a nie .Formula. Użycie .Formula nie jest tu formalnie błędem, ale zaciemnia kod.

    Moduł 4. Tu początek jest taki sam jak w module 3 i ten sam problem. Szukanie danych, których nie ma, a jeśli byłyby szukane w arkuszu2, to zostaną nadpisane kodem z modułu 3 i kod z modułu 4 już ich nie odnajdzie.
    Jeśli nie chcesz formuł, tylko wartości, to możesz je wyliczać w pętli.
    Albo zachowując to, co jest, po wypełnieniu zakresu formułami zamienić formuły na wartości.
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
    A jeszcze wcześniej jeśli używasz formuły w stylu R1C1, to trzeba ją przypisać do odpowiedniej wersji własciwości Formula:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    Nie załączam pliku, bo nie wiem jak chcesz rozwiązać ten początkowy fragment kodu, ale liczę, że sobie poradzisz.
  • REKLAMA
  • #19 20297158
    darkstar666
    Poziom 5  
    Posty: 22
    Witam. Poradziłem sobie z redukcją wierszy i zastosowałem .Value. Tu juz nie ma problemu.

    Ogólnie moduł 4 zależy od wykonanego modułu 3. Dlatego zachowuję taką kolejność.

    W module 3 chcę rzeczywiście wyszukać kolumny i zmienić później ich nazwę, dlatego teraz wstawiłem Dim w pętle, narazie wydaje się działać, ale proszę o weryfikację. Chce znajdywac numery kolumn, dlatego używam nazw zmiennych kWc i kW, ale potem używam tylko numerów ich kolumn (kWc.Column i kW.Column), chyba, że robię coś źle :/

    W module 4 chce tylko zamienić sztywnie wpisane kolumny D i E na znajdywane za pomocą ich nazw, jak wyżej.
  • #20 20297577
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Logika tego Twojego kodu jest dla mnie trudna do ogarnięcia.
    Na początku jesteś w arkuszu1 i sprawdzasz ostatni wiersz w kol. B - O.K.
    Potem w pętli przechodzisz kolejne arkusze i w każdym arkuszu:

    1) znajdujesz komórki z tekstami: "Wartosc calkowita" i "Waluta", nadając im nazwy obiektów: "kWc" i 'kW".
    Tu pierwszy błąd: musisz szukać tych tekstów w każdym arkuszu, czyli na początku pętli musi być:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    a nie:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    Z tych nazw będziesz mógł skorzystać prakytycznie jednorazowo, bo teksty na podstawie których je tworzysz za chwilę się zmienią i już tego kodu nie da się uruchomić ponownie w tym samym skoroszycie.

    2) taki dziwny kod:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    numer wiersza równy numerowi kolumny?
    Jeśli chodziło o zaznaczenie całej kolumny 'Waluta', to raczej tak:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    albo tak:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    albo:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    Ale czy to zaznaczanie w ogóle jest potrzebne?

    3) teraz wstawiasz 2 kolumny przed kolumną 'Waluta', która tym samym przesuwa się z kolumny E na G, kopiując formatowanie z kolumny D, która akurat zawiera "Wartosc calkowita"

    4) w kolejnym kroku kopiujesz formatowanie z kolumny kWc (D) do kolumny kW (G)

    5) na zakończenie obiegu pętli zmieniasz nagłówki posługując się oznaczeniami literowymi kolumn, a nie nazwami, które miały być do tego wykorzystane (jak zrozumiałem). Kolumna kWc ma teraz nagłówek: "Wartosc calkowita PLN", następna: "Wartosc calkowita EUR", kolejna "IR", ostatnia (do której jest przypisany obiekt kW) "Forecast". Wszystkie kolumny mają formatowanie skopiowane z kWc.

    Po zakończeniu obiegu pętli przechodzisz do następnego arkusza nadając nowe znaczenie obiektom kW i kWc itd.

    Czy tak to było pomyślane?

    Nie wiem jak chcesz wykorzystywać te arkusze, ale pisałem już, że tworzenie nazw w oparciu o teksty nagłówków, które za chwilę się zmienią nie jest dobrym pomysłem, bo jak coś pójdzie nie po myśli, to nie ma jak się cofnąć, chyba że będziesz tworzył za każdym razem kopie zapasowe.

    Nie załączam na razie poprawionej wersji i nie zaglądałem też jeszcze do modułu4, bo czekam na potwierdzenie lub korektę algorytmu.
  • #21 20301106
    darkstar666
    Poziom 5  
    Posty: 22
    Witam, poprawiłem kod, ale dalej mam błędy, mianowicie:
    1. With Activesheet.UsedRange działa bez problemu
    2. Columns(kW.Column).Select - tu wyrzuca mi błąd (info w komentarzy kodu makra)
    Czyżby to zaznaczenie nie było potrzebne, aby skopiować formatowanie z kolumny D do kolumn E, F, G. Poprawiłem źródło i kolumny docelowe kopiowania formatowania, ale tu też wyrzuca mi błąd taki jak wyżej.
    5. Poprawiłem automatyczne adresowanie, ale jeszcze nie wiem, czy działa, kod zatrzymuje się wcześniej.

    Kod ma być tak pomyślany, aby właśnie wykonywał te opracje dla wszystkich zakładek o nazwiach pobieranych z kolumny B Arkusza1. Będą raczeju żywane raz, ponieważ po przygotowaniu takiech arkuszy reszta dzieje się na formułach liczb, które obliczy tam moduł 4.
    Załączniki:
    • Trial2.zip (27.81 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #22 20301355
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Znowu namieszałeś w tym kodzie, ale nie rozumiem, jaki błąd masz w linii:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
    Tu nie powinno być żadnego błędu.

    Zaznaczanie kolumny jest zbędne. Na początku tworzysz zmienne obiektowe kW i kWc, a później nie umiesz ich wykorzystać.
    Poza tym, jak już poprzednio pisałem, kopiowanie formatowania jest zbędne, bo to formatowanie jest już kopiowane przy wstawianiu kolumn.

    W Module3 wystarczy taki kod:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod

    W swoim kodzie miałeś błędnie zdefiniowane obiekty Range.

    W Module4 należy zastosować podobne podejście. Przy automatycznym wypełnianiu kolumny z kwotami przeliczonymi na EUR, tło w ostatnim wierszu zostaje nadpisane. Ale ponieważ pewnie będziesz wypełniał i następne kolumny i podobny problem może wystąpić, to tło trzeba będzie uzupełnić na końcu, jak już wszystko będzie gotowe.

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
    Załączniki:
    • Trial3.zip (25.88 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #23 20312685
    darkstar666
    Poziom 5  
    Posty: 22
    Witam, mam już jaśniejszy pogląd na te moduły, rzeczywiście da się krócej napisać te procedury. Dziękuję.

    Które obiekty Range były błednie zdefiniowane i na co w tym przypadku mam zwracać uwagę?

    Grafiką komórek narazie się nie przejmuję, to temat kosmetyczny. Najbardziej zależy mi, aby kalkulacja działała bez problemów i intuicyjnie. Muszę przyznać, że napisany kod jest krótszy (polecenia są zwięzłe, ja bardziej pisałem jedno po drugim, aby prześledzić procedury krok po kroku). Mam jednak pytanie, czemu ma służyć wstawienie nowej zmiennej "ostd" i co ona definiuje? Nurtuje mnie też użycie offsetu w tej składni oraz dlaczego w autofillu jest resize i odejmowanie zmiennych w nawiasie? jak mam to rozumieć?

    Dziękuję z góry.
  • #24 20312801
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Które obiekty Range były błędnie zdefiniowane?

    Na przykład tu (i dalej):
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
    Przeczytaj sobie, jaka jest składnia odwołania do obiektu Range.
    Link
    Jest tam kilka wariantów, ale to co Ty napisałeś odpowiada raczej składni Cells niż Range, ale w przypadku Cells pierwszym argumentem jest numer wiersza, a drugim numer kolumny, a u Ciebie jest odwrotnie.
    Jeśli chodzi o Range oznaczający jedną komórkę, argumentem jest zazwyczaj tekst adresu w stylu A1.

    Zmienna ostd określa ostatni wypełniony wiersz w kolumnie "Wartosc calkowita PLN" w kolejnych przetwarzanych arkuszach.

    Offset jest używany kilka razy i nie wiem, o które użycie konkretnie pytasz. Jeśli o to:
    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
    to chodzi o komórkę położoną o wiersz niżej niż nagłówek kWceur, czyli komórkę, do której należy wpisać formułę.

    "dlaczego w autofilu jest resize"?
    Zakres docelowy w metodzie AutoFill musi obejmować wszystkie komórki, do których należy wprowadzić formuły. Wielkość tego zakresu trzeba jakoś obliczyć. Jednym ze sposobów jest użycie odwołania do pierwszej komórki (tu mamy kWceur.Offset(1)) i obliczenie do ilu wierszy należy ten zakres poszerzyć (Resize). Obliczamy to odejmując od numeru ostatniego wiersza (ostd) numer wiersza nagłówkowego (kWceur.Row).
  • #25 20517585
    darkstar666
    Poziom 5  
    Posty: 22
    Dziękuję, to rozwiewa moje wątpliwości na ten temat. Skrypt jest skończony i działa rewelacyjnie. Dziękuję bardzo :)

    Pojawił się kolejny temat:

    Napisałem skrypt, który powinien wykonywać następujące kroki po wciśnięciu guzika "Uzupełnij":
    1. Pobierać wartość z zaznaczonej komórki i wyszukiwać je w tej samej kolumnie, ale wyżej (pomijam warunek, żeby zaznaczenie zawsze było ustawione w kolumnie C).
    2. Przepisywać zawartość komórek z wyszukanego wiersza (od pierwszej z prawej do ósmej z prawej).

    Czyli na przykładzie z załącznika: jeśli przesunę zaznaczenie na komórkę C14, powinno pobrać wartość "5", wyszukać ją wyżej w tej samej kolumnie (znaleźć w C6) i wpisać do komórek D14-L14 to, co jest w komórkach D6-L6.

    Miał być jeszcze message box z informacją, że nie znalazło duplikatów, ale zrezygnowałem...

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod


    Mam wrażenie, że błąd siedzi w "LookAt:=xlWhole" i w "Cells(w1, k1 + 1).PasteSpecial xlPasteAll". Jak narazie nie rozwiązałem nieprawidłowego wpisywania w komórki.
    Załączniki:
    • Arkusz1.7z (18.27 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #26 20517699
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Chciałeś szukać duplikatu w kolumnie C od komórki powyżej zaznaczonej do komórki w pierwszym wierszu, czy tak?
    A gdzie szukasz?
    Cytat:
    ActiveSheet.UsedRange
    czyli w tym przypadku w zakresie od A1 do L15 wierszami, zaczynając od komórki następnej po zaznaczonej, czyli jeśli zaznaczona była pierwotnie komórka C14, to przeszukane będą komórki od D14 do L15, a następnie od A1 do A15. Pierwszą znalezioną z wartością 5 będzie komórka H1.
    Tu jest główny błąd. Masz szukać w kolumnie C (albo w kolumnie komórki aktywnej, czyli k1) w kierunku wstecz
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod
    , a wynik jeśli ma być do kolumny L, to to jest kolumna 9 (na prawo od C), a nie 8.
  • #27 20517841
    darkstar666
    Poziom 5  
    Posty: 22
    Ok, czyli zamiast "ActiveSheet.UsedRange" powinno być coś na kształt "Range(k1, 2)" - przeszukiwanie kolumny C od góry?

    Rozumiem, że zastąpić "LookAt:=xlWhole" tym: "SearchDirection:=xlPrevious"?

    A co dałoby usunięcie zapisów With (...) i End With i pozostawienie tego, co jest w środku? Na co to wpływa?

    Teraz wywala mi błąd 13, wcześniej go nie było :/
  • #28 20518334
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    "Cells(k1, 2)" to jest jedna komórka w wierszu k1 i w drugiej kolumnie, czyli raczej nie o to chodziło. A Range(k1, 2) to w ogóle błędna konstrukcja. Bardziej chodziło o "Columns(k1)".

    "SearchDirection:=xlPrevious" należy dopisać, ewentualnie zastąpić "MatchCase:=False", które tu jest bez znaczenia, bo szukasz liczb, a nie tekstów.
    "LookAt:=xlWhole" powinno zostać.

    Poza tym w
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod
    i następnym wierszu Cells jest zbędne.

    With .. End With można usunąć pod warunkiem, że wstawisz zakres przed Find, tzn.
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod
    Konstrukcja z With .. End With jest użyteczna gdy kilka razy odwołujemy się do tego samego obiektu. Tu jest tylko jedno takie odwołanie, więc można tę konstrukcję pominąć.
  • #29 20518674
    darkstar666
    Poziom 5  
    Posty: 22
    Teraz nie wywala żadnego błędu, ale nic nie wkleja i zostawia zaznaczenie :/

    Kod: VB.net
    Zaloguj się, aby zobaczyć kod
  • #30 20518712
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Okazuje się, że jeszcze trzeba dopisać w metodzie Find parametr
    Kod: VBScript
    Zaloguj się, aby zobaczyć kod
    On jest opcjonalny, ale w tym przypadku musi być użyty.

Podsumowanie tematu

✨ W dyskusji poruszono problem tworzenia arkuszy w Excelu za pomocą makr VBA, gdzie nazwy arkuszy są pobierane z określonego zakresu komórek. Użytkownik zainicjował temat, przedstawiając fragmenty kodu, które nie działały zgodnie z oczekiwaniami. Otrzymał pomoc w postaci poprawionego kodu, który dodaje nowe arkusze na podstawie wypełnionych komórek w kolumnie B, a także wskazówki dotyczące użycia funkcji WYSZUKAJ.PIONOWO w VBA. Użytkownik z sukcesem zaimplementował funkcjonalność wyszukiwania wartości w kolumnie oraz kopiowania danych z jednego arkusza do drugiego. W trakcie dyskusji omawiano również różnice między metodami odwołań do komórek oraz optymalizację kodu VBA.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA