Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Automatyczne rozdzielanie danych separatorem i obramowywanie tabeli

aurora23 04 Cze 2013 08:37 1614 10
  • #1 04 Cze 2013 08:37
    aurora23
    Poziom 10  

    Jestem początkującą użytkowniczką VBA (Excel 2010). Mam pewne zadanie do wykonania. Mianowicie:

    W Arkuszu1 posiadam tabelę z danymi (ilość wierszy w tej tabeli nie jest stała). Jedna kolumna w tej tabeli to numer konta oddzielany separatorami (Kropki). Moim zadaniem jest przeniesienie tej kolumny do sąsiedniego Arkusza2, do utworzonej już tabeli, w konkretną kolumnę, a następnie zastosowanie funkcji, która te dane rozdzieli tak, aby każdy element numeru konta był w innej komórce (w ten sposób z kolumny 1xn otrzymam tabelę 11xn, gdzie n to ilość rekordów w kolumnie Arkusza1).

    To co opisałam powyżej udało mi się zrobić, ale...

    1. Import danych do Arkusza2 psuje mi układ tabeli (nadpisuje komórki, które znajdują się poniżej i nie znajdują się w obrębie tabeli).

    2. Zaimportowane dane zostają rozdzielone funkcją ale tak jak powyżej, dane te nie są ani obramowane, a powyższy kod jest nieskuteczny, bo napotykając na komórkę która jest pusta wyskakuje Error.
    Przydałaby mi się tutaj pętla z licznika, ale nie wiem jak ją napisać.
    Proszę o pomoc.

    Kod: vb
    Zaloguj się, aby zobaczyć kod

    0 10
  • #2 04 Cze 2013 09:20
    marcinj12
    Poziom 40  

    Spróbuj po takiej przeróbce, jak coś nie będzie działać - dostosuj do własnych potrzeb:

    Kod: vb
    Zaloguj się, aby zobaczyć kod

    0
  • #3 04 Cze 2013 11:00
    aurora23
    Poziom 10  

    Dzięki serdeczne @marcinj12 za natychmiastową pomoc :)

    Jednak nie rozumiem tej części:

    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Co tutaj się dokładnie dzieje,
    czy deklaracja "Dim konto1_tab (odpowiednio konto2_tab) As Variant" jest poprawna?

    Błąd który się wyświetla to:
    "Can't assign to an array".

    W pomocy znalazłam coś takiego:
    Kod: vb
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #4 04 Cze 2013 13:18
    marcinj12
    Poziom 40  

    Już tłumaczę:
    Funkcja Split() jest funkcją VBA która rozdziela na tablicę swój argument - w tym wypadku wartość komórki .Cells(i, 5) - względem podanego separatora (kropka - drugi argument).
    W efekcie uzyskujesz tablicę składającą się z tylu elementów, ile "części" zwiera rozdzielany wyraz.

    Ja w moim kodzie nie deklarowałem zmiennych - jeżeli w module nie ma opcji Option Explicit to nie jest to wymagane. jeżeli masz i musisz / chcesz je zadeklarować, może to być:

    Kod: vb
    Zaloguj się, aby zobaczyć kod


    W dalszej części kodu w pętli For dla każdego elementu tablicy (odpowiednio: 1 lub 2) wpisujesz go w odpowiednią komórkę.

    0
  • #5 04 Cze 2013 15:04
    aurora23
    Poziom 10  

    Wielkie dzięki - to w porównaniu z moimi wypocinami ma ręce i nogi :D
    Jednak to do końca nie rozwiązuje mojego problemu nadpisywania uzupełnionych już wartości, zamiast przesuwania dołu arkusza bez naruszania jego treści i wartości w ogóle :/

    0
  • #6 04 Cze 2013 17:38
    marcinj12
    Poziom 40  

    Czy dobrze rozumiem, że chcesz za każdym razem po prostu DOPISYWAĆ dane do już istniejących w arkuszu "Nota_Oracle"?
    Jeżeli tak, to na przykładzie zmiennej ost_w możesz zobaczyć, jak ustalić ostatni niepusty wiersz w arkuszu. Zrób podobnie przy arkuszu z Oracla przed wejściem do pętli, a w pętli, zamiast uzależniać wiersz do którego wstawiasz od zmiennej i formułą: arkO.Cells(2 * i - 17, 10) [i podobne], użyj uzyskany numer wiersza, który zwiększysz o 2 czy o ile potrzebujesz w każdym kroku pętli.
    Jeżeli to chodzi o coś innego, to może załącz jakiś przykładowy plik z danymi i na nim wytłumacz, o co chodzi...

    0
  • #7 05 Cze 2013 11:32
    aurora23
    Poziom 10  

    Nie, chcę po włączeniu arkusza uzupełnić danymi tabelę w arkuszu "PK", potem klikam przycisk "Twórz notę " i chcę eksportować dane z czterech kolumn do arkusza "Nota_Oracle" (tu następuje rozdzielenie względem separatora).

    Dzięki Twojej pomocy udaje mi się zrobić (wraz z przesuwaniem wierszy).

    Jednak teraz mam kolejny problem:

    1. Ja zrobić, żeby po kolejnym Kliknięciu ComandButton'a procedura się nie powtarzała (czyli wolno mi było wykonać czynność wstawiania danych tylko jeden raz), bądź w "Nota_Oracle" tabela się automatycznie "korygowała" po ówczesnej edycji danych w "PK".

    A może warto ustawić arkusz "Nota_Oracle" na domyślnie pusty przy jego otwieraniu?

    kod wstawiania:

    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Załączam zdjęcia arkuszy - niestety nie mogę wstawić plików Excelowskich - nie jestem ich właścicielem :P

    0
  • #8 05 Cze 2013 18:26
    marcinj12
    Poziom 40  

    aurora23 napisał:
    Ja zrobić, żeby po kolejnym Kliknięciu ComandButton'a procedura się nie powtarzała (czyli wolno mi było wykonać czynność wstawiania danych tylko jeden raz), bądź w "Nota_Oracle" tabela się automatycznie "korygowała" po ówczesnej edycji danych w "PK".
    A w którym momencie czyścisz (usuwasz) z arkusza "Nota Oracle" te wiersze, które wstawiłaś po kliknięciu przycisku Utwórz notę?

    Najprościej chyba pod koniec kodu przycisku kopiującego wstawić:
    Kod: vb
    Zaloguj się, aby zobaczyć kod
    (oczywiście nazwa jest nazwą tego przycisku - zakładam że korzystasz z przycisków AciveX). Wtedy użytkownik dwa razy go nie wciśnie, a w arkuszu noty albo dodać jakiś przycisk "czyszczący" (usuwający) wiersze i ew. inne pola i odblokowujący przycisk z drugiego arkusza (tym razem nazwę przycisku musisz poprzedzić nazwą tego arkusza albo zmienną ustawioną na ten arkusz).

    Rozumiem, że po utworzeniu noty użytkownik może ją sobie zapisać przyciskiem Zapisz - może tam wrzucisz kod czyszczący notę i odblokowujący przycisk jej utworzenia?
    Zamiast czyścić arkusz, możesz też utworzyć jego "szablon", ukryć jego zakładkę, i zamiast usuwać wiersze i czyścić pola, każdorazowo go kopiować:
    Kod: vb
    Zaloguj się, aby zobaczyć kod


    PS. Dodaj do kodu:
    Kod: vb
    Zaloguj się, aby zobaczyć kod
    na początku i
    Kod: vb
    Zaloguj się, aby zobaczyć kod
    na końcu, oszczędź swoim użytkownikom migania na ekranie (i zyskaj sporo czasu przy okazji)...

    0
  • #9 05 Cze 2013 22:29
    aurora23
    Poziom 10  

    marcinj12 napisał:

    Najprościej chyba pod koniec kodu przycisku kopiującego wstawić:
    Kod: vb
    Zaloguj się, aby zobaczyć kod
    (oczywiście nazwa jest nazwą tego przycisku - zakładam że korzystasz z przycisków AciveX). Wtedy użytkownik dwa razy go nie wciśnie, a w arkuszu noty albo dodać jakiś przycisk "czyszczący" (usuwający) wiersze i ew. inne pola i odblokowujący przycisk z drugiego arkusza (tym razem nazwę przycisku musisz poprzedzić nazwą tego arkusza albo zmienną ustawioną na ten arkusz).


    okey, jeśli po pierwszym kliknięciu zablokuję przycisk to użytkownik pomyśl, że się "coś zepsuło".

    Chciałabym, żeby sytuacja wyglądała następująco:
    1. Klikam na przycisk z poziomu arkusza "PK".
    2. Jeśli w Arkuszu "Nota_Oracle" tabela była uzupełniona danymi to powyższe kliknięcie usuwa zawartość tabeli i jednocześnie wpisuje nowe dane z Arkusza "PK".

    Zatem funkcja czyszcząca musi znajdować się na samym początku funkcji przyporządkowanych to przycisku "Utwórz notę Oracle".

    Moja funkcja wygląda następująco:

    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Pierwsza czyści wartości pól, druga usuwa zbędne wiersze, tak aby domyślnie w tabeli były trzy puste wiersze).
    Druga nie działa tak jak powinna.... :(
    dzięki za wyrozumiałość i pomoc! :)

    0
  • Pomocny post
    #10 06 Cze 2013 01:06
    marcinj12
    Poziom 40  

    Takie czyszczenie w pętli nie jest zbyt efektywne: lepiej od razu wyczyścić cały zakres, jak już, to możesz przecież napisać:

    Kod: vb
    Zaloguj się, aby zobaczyć kod
    , a skoro i tak usuwasz pozostałe wiersze, czyszcząc jedynie 3, to po prostu:
    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Druga funkcja nie będzie działać z dwóch powodów:
    - po pierwsze: będziesz usuwać wiersze nawet, jeżeli arkusz będzie pusty
    - po drugie: usuwając w pętli od k = 16 do m, będziesz usuwała kolejne zwiększające się numery wierszy, chociaż po każdym kroku pętli będzie o jeden mniej i przesuną się one do góry. Jeżeli już, usuwaj w tej pętli zawsze wiersz 16.

    Ja natomiast bym to rozwiązał inaczej: pętlą For albo funkcją Find aż do ostatniego wiersza, znalazł numer wiersza jakiegoś stałego "znacznika" końca usuwania, np. szukał wartości Sporządził:, sprawdził, czy jest on większy niż 17, a jeżeli tak, usunął:
    Kod: vb
    Zaloguj się, aby zobaczyć kod


    PS. Zmienna ost_w1 powinna być typu Long, nie String. Nie musisz też robić Set arkO, jeżeli tego nie używasz - w zupełności wystarczy wrzucić nazwę tego arkusza bezpośrednio do With.

    0
  • #11 06 Cze 2013 13:24
    aurora23
    Poziom 10  

    Serdeczne dzięki :) Zastosowałam się do porad i wszystko gra.

    Temat uznaję za zamknięty :)

    0