Corel FORUM
Forum użytkowników programów firmy Corel. Grafika wektorowa, rastrowa i obróbka zdjęć cyfrowych

Makra - wczytanie danych ze schowka

Anakonda64 - 20 Lipiec 2013, 18:16
Temat postu: wczytanie danych ze schowka
Potrzebuje wczytać w makrze dane ze schowka. Dane są w postaci tablicy 2 na 10 (skopiowanie z arkusza excelowskiego). Mam w VBA zadeklarowaną tablice z danym (właśnie 2 na 10 - określają współrzędne 10 obiektów) i Kombinowałem z GetFromclipboard, ale coś pewnie nie do końca umiem to zastosować. Czy ktoś mógłby mi w tym pomóc?
Pozdrawiam seredcznie

chezare - 21 Lipiec 2013, 07:48

Tablica 2x10 to w vba 33 dane, a nie 20, a tym bardziej 10 :-)
Nie mam Excela i nie bardzo mam jak prowadzić eksperymenty, ale metoda, którą chcesz to zrealizować na pewno nic nie da, w taki sposób, to dostaniesz co najwyżej tekst, a do tego żadna tablica nie jest potrzebna.
Oczywiście taki tekst można podzielić na Fragmenty, które w Excelu stanowiły zawartość poszczególnych komórek, ale to dodatkowa robota.
Sam pomysł wydaje mi się bez sensu, kopiujesz dane z Excela, przechodzisz do Corela i uruchamiasz makro? Do czego taki mechanizm może się przydać? Jeśli to ma być jakaś baza danych, to przygotuj gotowy plik, który Corel będzie mógł wykorzystać, to minuta roboty.
Dzięki VBA, na pewno da się przeczytać dane bezpośrednio z arkusza kalkulacyjnego, metoda którą wymyśliłeś wydaje mi się delikatnie mówiąc. dyskusyjna.

Anakonda64 - 21 Lipiec 2013, 09:57

Dziękuje za odpowiedź. 33 dane jak zaczynasz liczyć od zera. Jak liczysz 1 do 10 i 1 do 2 masz 20 danych ( mam stare nawyki jeszcze z fortranu :) - dziadek jestem), to współrzędne 10 obiektów (x, y). Rozumiem, że rutyna się kłania :). Jasne że da się odczytać bezpośrednio z komórek excela. Natomiast ze względu na to że te dane pojawiają się w różnych plikach, automatyzacja odczytu jest mało realna. Mógłbym oczywiście zapisywać dane z excela w pliku tekstowym, po to ,żeby potem odczytać je w VBA. Chyba jednak schowek jest naturalniejszy :). Stad przez schowek. Ogólnie sytuacja jest taka. Niewazne excel czy nie excel. Mam w schowku 20 danych. ( można to tez potraktować jako jedną string, albo 10 string w tablicy 1 kolumnowej ) - obojętne dam sobie radę z przekształceniem. Tylko jak mam odczytać ten schowek :0 . Funkcja dana = clipboard.getText wyrzuca bład
chezare - 21 Lipiec 2013, 12:02

A jesteś pewny, że to jest tekst?
Anakonda64 - 21 Lipiec 2013, 18:03

W jakim sensie czy jestem pewny że tekst. Czytanie ze schowka da chyba zawsze tekst? I tak też zawartość schowka jest chyba traktowana? Chyba zawsze jest taka składnia .GetTekst przy czytaniu schowka?
Czytam do schowka liczby 2 kolumny po 10 rzędów. Widziałem działające makra w corelu, które tak wczytują liczby lub tekst - obojętne. Natomiast tym .GetTekst próbowałem tez tekst wczytać i tez wywalał błąd. Być może jakaś inna składnia w VBA dla corela której niestety nie znam a poszukiwania netowe niewiele dały - coć co prawda znalazłem, ale gorzej ze zrozumieniem :)

chezare - 22 Lipiec 2013, 06:22

Nie chciałbym żebyś traktował to co teraz napiszę jako konkretną wiedzę, bo takiej na ten temat nie posiadam i mogę się mylić, ale wydaje mi się, że nie masz racji.
Moim zdaniem w windowsowym schowku, oprócz samych danych znajduje się również informacja jakiego typu są te dane, dlatego w Excelu można skopiować fragment arkusza i wkleić w inne miejsce z zachowaniem formatowania, można też wkleić np. obrazek. Nie da się jednak w sposób kopiuj, wklej przenieść dowolnych danych z jednego programu do dowolnego innego, choćby z tego prostego powodu, że dany program jakiegoś typu danych nie obsługuje, gdyby to był tekst, to dawałoby się praktycznie zawsze to zrobić, w końcu każda informacja cyfrowa to w jakimś sensie tekst.
Wszyscy powyjeżdżali i niestety mam roboty więcej niż jestem w stanie zrobić, ale jak znajdę chwilę czasu to mogę pomajstrować przy obsłudze schowka w VBA, choć moja wiedza w tym temacie w tym momencie jest dosyć mizerna, żeby nie powiedzieć żadna.
Nie wydaje mi się jednak, żeby to było takie proste?
==========
Na forum był już podobny temat, choć problem był dokładnie odwrotny, chodziło o przeniesienie danych z Corela do Excela. Rzuć okiem może Ci się coś rozjaśni?
MaroQ na pewno dałby sobie z tym radę :-)
http://corel.wodip.opole....opic.php?t=5741
Gdybyś napisał konkretnie co chcesz zrobić, to pewnie byłoby łatwiej.
Podaj konkretny przykład, xls i cdr i co ma się stać po wykonaniu makra.

Mówisz, że taki sposób jest prostszy, ale jaki on prostszy jak musisz modyfikować za każdym razem kod makra? Przyszło mi też do głowy inne rozwiązanie, a mianowicie takie, że jak się nie da zrobić tego w prosty sposób w Corelu, to może dobrze by było spreparować do czytelnej postaci kopiowane dane z Excela, tam też przecież jest VBA i to moim zdaniem znacznie sprawniejsze niż to z Corela.

Anakonda64 - 22 Lipiec 2013, 07:58

Wiesz, siedze nad tym tematem dosyć długo. W ogóle tych prac :) , a nie tego kodu VBA. Mam następujące zadanie. Excel oblicza mi wspólrzedne wierzchołków wykresu liniowego - czy tez obrysu - to też zależy od konkretnego zadania. Z tym że liczy mnóstwo , a ja musze sam wybrać właściwe - to nie da się zautomatyzować. Dotąd radziłem sobie tak że robiłem wykres w excelu, przenosiłem go jako meta do corela i miałem linie - skalowalem mierzac odległości wierzchołków, do tego robiłem obrys coby zlikwidować pdowójna zaplatana często , pootwieraną częściowo linie - róznie się to wczytuje. I to chciałem uprościć - od razu rysować w corelu. Dane jak jest nawet 20 :) da się wczytać przez okno - i tak będzie szybciej niż pieprzenie się z czyszczeniem tego wykresu z excelu. Ale czasami mam krzywą z 1000 punków, a to już zajmuje więcej czasu. Narysować , okreslic atrybuty, wyskalować potrafie w kodzie, ale jak te dane wczytać :)
Makra nie trzeba modyfikować. Z iloscią wierzchołków tez sobie poradzę, żeby to czytac i odpowiednio rysować , a to jedyne zmienne oprócz danych wierzchołków w makrze

chezare - 22 Lipiec 2013, 10:46

Rozumiem.
maroQ - 28 Lipiec 2013, 20:23

Anakonda64 napisał/a:
skopiowanie z arkusza excelowskiego

Czyli w wierszu dane są rozdzielone tabulacją. Może być, podobnie jak CSV z punktu widzenia makra jest mało problematyczny. Komunikacja z Excelem bywa problemem tj. zachowanie zgodności referencji po zmianie komputera (inny excel itp.), ale są już gotowe biblioteki które ten problem rozwiązują, w każdym razie to nieistotne w tym momencie.

Anakonda64 napisał/a:
mam stare nawyki jeszcze z fortrana

Fortrana można używać z VBA lub .NET, ale tylko jeśli utworzy się bibliotekę dll. W G95 bardzo ładnie to działa bo już to sprawdzałem jakiś czas temu. Fortran ma tylko jedną wadę tj. trzeba przekompilować binarkę osobno dla x86 i x64. Dodatkowo dzięki Dislin lub Gnuplot (zależnie od tego co komu bardziej pasuje) umożliwia tworzenie wykresów, a nawet prostych kontrolek i programów windowsowych (prościej jest to jednak zrobić w .NET). Zresztą wygląd wykresów z Gnuplot, Dislin czy Matlab, Scilab jest zawsze mniej ładny niż ten z Excel (2007 lub nowszy) lub .NET. Niby w tych wszystkich programach inżynierskich można dopiąć aproksymację, ale chyba przez brak dobrego renderingu wykres zawsze jest postrzępiony. Wspomniany .NET (VC++, VB.NET, C#, J#, itp.) daje całkiem ładne wykresy czy kontrolki ponieważ można tam użyć renderingu. Tracimy trochę wydajności, ale wygląd jest tego wart. Przy okazji wykresów kiedyś poprawiałem je w Photoshopie co dawało bardzo fajne efekty, ale to inny temat.


No to koniec szamanienia i przechodzimy do faktycznego tematu.
Kod:
Sub GetExcelMatrix()
'
' Pobiera dane ze schowka i próbuje przerobić je na macierz
'
    On Error Resume Next
   
    Dim clip As DataObject
    Dim strClip As String
   
    Set clip = New DataObject
    clip.GetFromClipboard
    strClip = clip.GetText
    Dim x As Integer, y As Integer
    Call GetMatrixSizes(strClip, x, y)
    MsgBox "kolumn:    " & x & vbTab & vbNewLine & "wierszy:" & vbTab & y, vbInformation, "Jaka macierz"
   
    Dim arr() As String
    Call GetMatrixData(strClip, arr, True)
   
End Sub

Private Function CountChar(ByRef txt As Variant, ByVal ch As String) As Integer
'
' Oblicza ilość wystąpień szukanego znaku w stringu
'
    Dim i As Integer
    Dim j As Integer
   
    For i = 1 To Len(txt)
        If Mid(txt, i, 1) = ch Then
            j = j + 1
        End If
    Next i
    CountChar = j
End Function

Private Sub GetMatrixSizes(ByVal txt As String, ByRef x As Integer, ByRef y As Integer)
'
' Oblicza ilość wierszy i kolumn pobranych z Excela do schowka
'
    Dim arr() As String
    Dim row As Variant
    Dim i As Integer
    Dim max As Integer
    y = CountChar(txt, vbCr) 'licz ile "powrotów karetki"
    ReDim arr(y)
    txt = Replace(txt, vbLf, "") 'wywal znaki końca linii
    arr = Split(txt, vbCr)
       
    For Each row In arr
        x = CountChar(row, vbTab)
        If x > max Then
            max = x
        End If
    Next row
   
    x = max + 1
End Sub

Private Sub GetMatrixData(ByVal txt As String, ByRef arr() As String, Optional showit As Boolean = False)
'
' Zamienia macierz z Excela na macierz stringów
'
    Dim x As Integer, y As Integer
    Dim i As Integer, j As Integer
    Dim item As String
   
    Call GetMatrixSizes(txt, x, y)
    Dim rows() As String
    Dim cols() As String
   
    txt = Replace(txt, vbLf, "") 'wywal znaki końca linii
    rows = Split(txt, vbCr)
   
    ReDim arr(x, y)
    For i = 0 To y - 1
        cols = Split(rows(i), vbTab)
        item = item & "["
        For j = 0 To x - 1
            arr(j, i) = cols(j)
            If j = x - 1 Then
                item = item & Replace(cols(j), ",", ".")
            Else
                item = item & Replace(cols(j), ",", ".") & ","
            End If
        Next j
        item = item & "]" & vbNewLine
    Next i
   
    If showit Then
        MsgBox item, vbInformation, "Macierz:"
    End If
End Sub

Powyżej masz zabawkę tj. GetExcelMatrix() obecnie jest to tylko szkielet tego czego zapewne potrzebujesz.

Działa to tak:
CountChar - oblicza ilość wystąpień znaku w stringu (niestety w VBA nie ma Char, więc trzeba marnować pamięć lub użyć Byte, ale wtedy konieczne jest użycie Asc() i Chr() co się nie opłaca).
GetMatrixSizes - oblicza ile masz wierszy i kolumn w ciągu tekstowym zakładając, że nowy wiersz to nowa linia, a nowa kolumna to znak tabulacji.
GetMatrixData - pobiera macierz stringów (tak jest zawsze bezpieczniej), możesz to sobie przerobić na pobieranie Integer lub Double, ewentualnie Single (bardziej optymalne niż Double). W polskiej wersji Windows używamy przecinka, a w angielskiej kropki, by to ujednolicić zawsze należy zamieniać w ciągu "," na "." lub odwrotnie by uniknąć błędów i zapewnić przenośność kodu. W .NET da się wykryć znak przecinka lub kropki i uczynić kod bardziej odpornym. Funkcję wywołujesz tak: GetMatrixData(tekst, tablica_znaków) lub GetMatrixData(tekst, tablica_znaków, true) jeśli chcesz zobaczyć co widzi VBA.

Obsługę schowka masz w GetExcelMatrix(), msgboxy można pousuwać.

P.S. Ilość wierszy i kolumn nie ma większego znaczenia.

chezare - 29 Lipiec 2013, 07:18

Identyczną konstrukcję znalazłem w wielu miejscach w sieci.
Niestety działa to tak, że nie działa :-)

Wykoleja się na pierwszej deklaracji (X3),
Dim clip As DataObject
W Twoim kodzie nie ma błędu, przynajmniej w tym fragmencie, taki stan rzeczy występuje nie tylko w Corelu ale również w Excelu.
Tu jest rozwiązanie problemu:-)
http://blog.jonschneider....d-type-not.html

W świeżo zainstalowanym Windowsie (XP) i świeżo zainstalowanym X3, ta opcja nie jest zaznaczona.
Resztę kodu można chyba znacznie uprościć.
Kolega czyta zawsze z Excela po dwie pary liczb (wsp. punktu) z dwóch sąsiadujących kolumn. Nie mam Excela ale dane w schowku pewnie wyglądają tak:
liczba <tab> liczba <cr>
liczba <tab> liczba <cr>…
Pomyślałem, że chyba można w ogóle obejść schowek, bo przecież jego sytuacja wygląda tak, że ma otwartego Excela i zaznaczony obszar z danymi. Wciska ctrl+C i przechodzi do Corela. Ctrl+C i schowek prawdopodobnie da się ominąć?
Pytanie jest takie, czy da się przeczytać w VBA Corela jaki obszar jest zaznaczony w Excelu?

maroQ - 29 Lipiec 2013, 09:37
Temat postu: Przychodzi baba do lekarza z ręką i nogą w gipsie...
chezare napisał/a:
Wykoleja się na pierwszej deklaracji (X3)

Nie pomyślałem, że ktoś może chcieć uruchomić makro z VBAProject czyli z otwartego dokumentu. Ja pracuję w GlobalMacros lub osobnych plikach GMS, gdzie ten problem nie występuje. Staram się nigdy nie pracować na otwartych plikach bo w ten sposób straciłem już sporo kodu w przeszłości kiedy to omyłkowo usunąłem plik corela z makrami.

Druga sprawa o której nie pomyślałem to to, że zawsze w Global Macros mam jakiś User From więc wspomniana referencja jest zawsze dodawana. Tak to jest jak się robi program na szybko.

Cytat:
schowku pewnie wyglądają tak:
liczba <tab> liczba <cr>

Nie do końca, ponieważ w Windows poza znakiem powrotu karetki (CR) jest jeszcze znak końca linii (LF) który w zamieszczonym kodzie jest usuwany.
Ogólnie zakończenie linii wygląda tak:
Windows -> CRLF
Unix/Linux -> LF
MAC -> CR

chezare napisał/a:
Pytanie jest takie, czy da się przeczytać w VBA Corela jaki obszar jest zaznaczony w Excelu?

Nie bardzo... Mimo wielu prób w przeszłości nie udało mi się nigdy uzyskać takiego dostępu. Nie ma problemu z dostępem do zapisanego pliku przez referencje do Excela lub przez ODBC (lub OLEBC), ale nie mam pojęcia jak dostać się do otwartego okna Excela. Wywołanie konstruktora dla referencji Excela otwiera nowe okno (przy kontakcie przez wrapper) Excela ewentualnie nie otwiera nic i uruchamia proces w tle (np. dostęp z Corela przez referencje). Druga sprawa to to, że kopiując dane do schowka lub zapisując je jako csv/txt itp. obecność Excela w systemie nie jest wymagana. Można użyć WordPerfect Office, Libre Office (następca Open Office), Open Office, Star Office itp. zamiast Excela i też będzie działać. Podobnie wygląda obsługa programów .NET z DataGridView ale tam wszystko zależy od ustawień użytkownika.

Prosty test dla Excela (trzeba dodać Excela w referencjach w Corelu, jednocześnie mając odpalonego Excela i otwarty jakikolwiek dokument).

Kod dla Corela:
Kod:
Sub ex()
    Dim xls As New Excel.Application
    MsgBox xls.Workbooks.Count
End Sub


Kod sprawdzający dla Excela:
Kod:
Sub ex()
    MsgBox Workbooks.Count
End Sub


Użycie "New" powoduje utworzenie nowego obiektu Excela czyli brak możliwości dostępu do otwartego okna. Analogiczna sytuacja z dostępem do Corela daje możliwość odczytu aktywnego okna Corela (zmiana aktywnego procesu i mamy dostęp do innych cech).

Przykład makra dla Excela (referencje: CorelDraw i Vector Graphics Core):
Kod:
Sub cor()
    Dim draw As New CorelDRAW.Application
    MsgBox draw.ActiveDocument.Name
End Sub


Powered by phpBB modified by Przemo © 2003 phpBB Group