SOBasicHELP.pl - Witryna ta poświęcona jest językowi StarBasic. Pozdrawia Vbadam! Powrót na str.0
Komentarz
do tego tłumaczenia.
Niestety niektóre makra z podręcznika andrewmacro nie działają od razu (!!!)
bo są wyrwane z kontekstu.
Nie jeden początkujący makrarz może się nam zniechęcić
i po prostu "pieprznąć tym w cholerę" (czytaj -
pozostać przy jedynie słusznym VBA).
Dlatego, makra
z andrewmacro (tylko te które
przetłumaczyłem)
uzupełniłem, poprawiłem i przetestowałem tak, aby od
razu zadziałały.
Przepraszam więc za niezgodność z oryginałem ! Przepraszam też,
że dodałem komentarze.
Poniższe
makra można przetestować przy pomocy plików-trenażerów,
które są do ściągnięcia przez poniższe linki:
Makra do
Calc'a*:
operacjenakomorkach_oo11.zip,
select_szukaj_tekst.zip
Makra ogólne do OOo*:
andrzejmakro_pl.zip (jest to tłumaczenie
z makrami w jednym)
*Można sobie próbować też otwierać
te przykłady bezpośrednio w oknie przeglądarki:
operacjenakomorkach_oo11.sxc,
select_szukaj_tekst.sxc
oraz dokument
andrzejmakro_pl.sxw
Oryginał jest na stronie http://www.pitonyak.org/
Poniżej są fragmenty przetłumaczone przez Adam Grążka
Spis
treści (już przetłumaczone ustępy):
[...]
3.1 Nasze pierwsze makro: wyświetlenie "Witamy
Pięknie".
[...]
6 Makra w Calc'u
5.21* Kopiowanie do/ze schowka systemowego (Clipboard).
5.21.1* Kopiowanie komórek arkusza calc'a za
pomocą schowka systemowego (Clipboard).
5.21.2* Kopiowanie komórek arkusza bez użycia
schowka systemowego.
6.1 Czy jest dostępny dokument typu arkusz
kalkulacyjny?
6.2 Prezentacja wartości, tekstu i formuły z
aktywnej komórki
6.3 Umieszczanie wartości, tekstu i formuły
w aktywnej komórce
6.4 Czyszczenie komórki
6.5 Wybieranie tekstu (zaznaczanie i
pobieranie), Jak to jest?
[...]
8.2 Dialogi
[...]
*podrozdział 5.21 jest tutaj przywołany bo traktuje o Calc'u
Otwieramy nowy dokument OOo. Klikamy na Narzędzia->Makra->Makro. Otworzy się okno dialogowe Makro. W lewej części tego okna jest pokazana struktura dostępnych obiektów, które są "nosicielami" makr (to jest Makro z), wyszukujemy tu dokument który właśnie otworzyliśmy. To będzie prawdopodobnie Bez tytułu1 (szukajcie na dole tej listy, bo program domyślnie ustawia się na górze). Pojedynczo klikamy zaraz poniżej Bez tytułu1 dokładnie tam gdzie jest Standard. Następnie klikamy w guzik Nowy (to jest trzeci przycisk od dołu po prawej &ldquoguzikowej&rdquo stronie okna Makro). Służy on do tworzenia nowych modułów. W tym miejscu zawsze proponowana jest domyślna nazwa dla nowego modułu Module1. Taka domyślna nazwa nie jest nie najlepszym wyborem, gdyż kiedy będziemy mieć otwartych wiele oddzielnych dokumentów i we wszystkich będziemy mieli moduł nazwany Module1, to może być bardzo trudnym odnoszenie się do poszczególnych modułów z osobna. Dlatego, nazwę naszego pierwszego modułu określamy jako np. MojPierwszyModul. Dopiero teraz OOo Basic IDE można uznać jako otwarty (możliwa jest edycja makr). Modyfikujemy kod w ten sposób, aby wyglądał tak jak pokazany poniżej (w ramce):
| REM ***** BASIC
***** Sub Main Print "Witamy pięknie" End Sub |
Aby sprawdzić w działaniu nasze pierwsze dzieło programistyczne, klikamy na odpowiedni przycisk (z kartką i strzałką w dół z boku) dostępny w aktywnym OOo Basic IDE.
?? Zobaczcie developers guide strona 331!
Nie wiem czy to są najlepsze metody do dostępu do schowka systemowego, ale można być pewnym, że to co jest tutaj zaprezentowane, na pewno gdzieś, kiedyś i dla kogoś pracowało.
Przed skopiowaniem danych do schowka (clipboard), musimy po pierwsze wybrać te dane. Do tego służy spacjalny interfejs osiągalny przy pomocy następującej konstrukcji com.sun.star.view.XSelectionSupplier , który posiada specjalne elementy zdolne do wybierania i dostępu do aktualnie wybranych (zaznaczonych) obiektów. Są tam udokumentowane opisy specjalnych sekcji służących do podejmowania wybranego tekstu zarówno w arkuszach calc'a jak i w dokumentach writer'a.
W poniższym przykładzie, pobieram zaznaczone komórki z jednego skoroszytu arkusza kalkulacyjnego i wklejam je do innego (oddzielnego) skoroszytu arkusza.
'Autor: Ryan Nelson
'email: ryan@aurelius-mfg.com
'Makro kopiuje zaznaczony obszar i kopiuje to do nowego lub otwartego dokumentu *.sxc
Sub CopyPasteRange()
'Na początek włączamy tą bibliotekę, która pozwoli na użycie funkcji DispatchSlot.
GlobalScope.BasicLibraries.LoadLibrary("Tools")
'deklaracje zmiennych do przenoszenia obiektów źródłowych:
Dim oSourceDoc As Object, oSourceSheet As Object, oSourceRange As Object
'deklaracje zmiennych do przenoszenia obiektów docelowych:
Dim oTargetDoc As Object, oTargetSheet As Object, oTargetCell As Object
Dim sUrl As String
'ustalamy żródło czyli obszar do skopiowania - doc/sheet/range.
oSourceDoc=ThisComponent 'aktualnie otwarty dokument
oSourceSheet= oSourceDoc.Sheets(0) 'sposób 1 na wybranie konkretnej kartki (arkusz1)
'sposob 2*...oSourceDoc.Sheets.getByName("Arkusz1") *zadziała tylko w polskiej ver.
'sposob 3 ....oSourceDoc.Sheets.getByIndex(0)
'obiektZródło=doc/sheet/range.getCell...(LewySkraj,GórnySkraj,PrawySkraj,DolnySkraj)
oSourceRange = oSourceSheet.getCellRangeByPosition(0,5,100,10000)
'wybranie wyżej określonego obiektu (w Excelu też jest "select", ale użyty po kropce)
ThisComponent.CurrentController.Select(oSourceRange)
'wkopiowanie aktualnie wybranego obiektu do schowka systemowego (do clipboard)
'tu jest użyta nowa funkcja z dodatk. biblioteki Tools (jest umieszczona w module Misc)
DispatchSlot(5711) 'COPY - patrz indeks komend: commands_103.html
'określamy obiekt oDesk w syst. UNO(Universal Network Objects) jako Desktop
oDesk = createUnoService("com.sun.star.frame.Desktop")
'Ustalamy URL do dokumentu [info o URL'ach}, który jest już otwarty lub otwieramy nowy arkusz calc.
sUrl = "File:///C:/temp/testing2.sxc"
'otwieranie dokumentu calc.
Dim NoArg()
oTargetDoc=oDesk.loadComponentFromURL(sUrl,"_blank",0,NoArg())
oTargetSheet = oTargetDoc.Sheets(0)
'Możemy być zmuszeni oczyścić obszar docelowy przed wklejeniem do niego
'zawartości schowka, jeżeli zawiera dane i/lub niestandardowe formatowanie.
'Wymuszamy przeniesienie focusa do komórki(0,0).
'To zapewnia nam że rozpoczniemy wklejanie od komórki(0,0).
'Możemy ustalić sobie oczywiście inną komórkę.
'Ale jeżeli nie ustalimy w ogóle takiej pozycji, to możemy być narażeni na
'niekontrolowane wklejenie począwszy od punktu, który pozostał ustawiony
'w ostaniej sesji edycji tej kartki arkusza, kiedy to była ostatnio otwarta.
oTargetCell = oTargetSheet.getCellByPosition(0,0) 'ustalenie obiektu docelowego
oTargetDoc.CurrentController.Select(oTargetCell) 'wybranie wyżej określonego obiektu
'ostateczne wklejenie danych ze schowka do aktualnie wybranego obiektu.
DispatchSlot(5712) 'PASTE - patrz indeks komend: commands_103.html
End Sub
W tym przykładzie do
kopiowania do/ze schowka użyto metody DispatchSlot. Pełna lista
akceptowanych komend liczbowych (slots) w wersji 1.0.3.1 można
zobaczyć pod tym adresem:
http://www.openoffice.org/files/documents/25/60/commands_103.html
Inną formą stosowaną przy kopiowaniu o której coś wiem, jest
użycie dyspozycji w następującej formie: ".uno:Copy"
and ".uno:Paste".
Kopiowanie obszaru komórek
w ramach tego samego arkusza, to nie jest powód do wykorzystania
do tego celu schowka systemowgo (Clipboard). Arkusz kalkulacyjny
jest zdolny operować komórkami i obszarami "we własnym
zakresie". Można tu komórki kopiować, wstawiać, usuwać
i przemieszczać z jednego miejsca do innego w obrębie tego
samego arkusza. Aby dowiedzieć się więcej na ten temat zobacz
na:
http://api.openoffice.org/docs/common/ref/com/sun/star/sheet/XCellRangeMovement.html
Poniższy kod był wysłany na forum devapi.
******************************************************************
' Author: Oliver Brinzing
' email: OliverBrinzing@t-online.de
Sub CopySpreadsheetRange
oSheet1 = ThisComponent.Sheets.getByIndex(0) ' sheet no 1, oryginal
oSheet2 = ThisComponent.Sheets.getByIndex(1) ' sheet no 2
oRangeOrg = oSheet1.getCellRangeByName("A1:C10").RangeAddress ' obszar oryginału
oRangeCpy = oSheet2.getCellRangeByName("A1:C10").RangeAddress ' obszar do wklejenia
oCellCpy = oSheet2.getCellByPosition(oRangeCpy.StartColumn,_
oRangeCpy.StartRow).CellAddress ' insert position
oSheet1.CopyRange(oCellCpy, oRangeOrg) ' kopiowanie...
End Sub
*******************************************************************
'Makro powstało na podstawie kodu napisanego przez Oliver Brinzing
'Makro przerobił i sprawdził Adam Grążka [adamgra@poczta.onet.pl]
Sub KopiujWyznaczonyObszarSposZerowy
oSheet1 = ThisComponent.Sheets.getByName("Arkusz1") 'ark.nr1 (tu wkopiowujemy)
'oSheet1 = ThisComponent.Sheets.getByIndex(0) 'opcj. sposób na wyróżnienie ark1
oSheet2 = ThisComponent.Sheets.getByName("Arkusz2") 'ark.nr2 (stad pobieramy dane)
'oSheet2 = ThisComponent.Sheets.getByIndex(1) 'opcj. sposób na wyróżnienie ark2
oObszarZrodlowy = oSheet2.getCellRangeByName("A1:A10").RangeAddress
WspolzedneWklejenia = oSheet1.getCellByPosition(0,0).CellAddress
'ustalenie pozycji komorki wyznaczajacej miejsce docelowe wklejenia
oSheet1.CopyRange(WspolzedneWklejenia, oObszarZrodlowy)
'ostateczne skopiowanie...
End Sub
Dokument typu arkusz kalkulacyjny jest tak skonstruowany, że są w nim arkusze. Zanim użyjemy specyficznych metod związanych z arkuszem kalkulacyjnym, musimy mieć koniecznie otwarty jakiś dokument tego typu. Można weryfikować ten stan w taki sposób, że wywołujemy z dowolnego makra poniższą funkcję, która powinna być umieszczona w modułach aplikacji (w modułach zawsze dostępnych np. w takim miejscu => Soffice/Standard/Module1):
Function CzyToJestCalc(oDoc) As Boolean
On Local Error GoTo NODOCUMENTTYPE
CzyToJestCalc =oDoc.SupportsService("com.sun.star.sheet.SpreadsheetDocument")
NODOCUMENTTYPE:
If Err <> 0 Then
CzyToJestCalc = False
Resume GOON
GOON:
End If
End Function
Przykładowe wywołanie powyższej funkcji ma postać jak niżej i może być umieszczone w ciągu dowolnej procedury (MsgBox... użyto tu tylko w celu uwidocznienia wartości zwracanej przez funkcję) :
Sub Main
Dim oDoc As Object
oDoc=ThisComponent
MsgBox CzyToJestCalc(oDoc)
End Sub
'******************************************************************
'Author: Sasa Kelecevic
'email: scat@teol.net
Sub PokazZawartoscKomorki
Dim oDocument As Object, oSheet As Object, oCell As Object
oDocument=ThisComponent 'wybór obiektu(w VBA odpowiednikiem będzie Selection)
oSheet=oDocument.Sheets.getByName("Arkusz1") 'wyróżnienie arkusza nr1
oCell=oSheet.getCellByposition(0,0) 'wyróżnienie komórki A1
print oCell.getValue 'prezentacja wartości liczbowej z wyróżnionej komórki
print oCell.getString 'prezentacja łańcucha z wyróżnionej komórki
print oCell.getFormula 'prezentacja formuły zawartej w wyróżnionej komórce
End sub
'******************************************************************
'Author: Sasa Kelecevic
'email: scat@teol.net
Sub ZmienWartoscKomorki
Dim oDocument As Object, oSheet As Object, oCell As Object
oDocument=ThisComponent 'wybór obiektu(w VBA odpowiednikiem będzie Selection)
oSheet=oDocument.Sheets.getByName("Arkusz1") 'wyróżnienie arkusza nr1
oCell=oSheet.getCellByPosition(0,0) 'wyróżnienie komórki A1
oCell.setValue(23658) 'wpisanie wartości liczbowej do wyróżnionej komórki
'oCell.NumberFormat=2 'określenienie sposobu prezentacji liczby (23658,00)
'oCell.SetString("oops") 'wpisanie łańcucha tekstowego do wyróżnionej komórki
'oCell.setFormula("=FUNCTION()") 'wpisanie formuły do wyróżnionej komórki
'oCell.IsCellBackgroundTransparent = TRUE 'określenienie ...?
'oCell.CellBackColor = RGB(255,141,56) 'określenienie koloru dla tła w komórce
End Sub
Lista tematów dotycząca oczyszczania komórek może być osiągalna pod adresem: http://api.openoffice.org/docs/common/ref/com/sun/star/sheet/CellFlags.html
'******************************************************************
'Author: Andrew Pitonyak
'email: andrew@pitonyak.org
Sub CzyszczenieWyznaczonegoObszaru
Dim oDocument As Object, oSheet As Object, oSheets As Object, oCellRange As Object
oDocument = ThisComponent
oSheet=oDocument.Sheets.getByName("Arkusz1")
oCellRange = oSheet.getCellRangeByName("A1:A10")
oCellRange.clearContents( com.sun.star.sheet.CellFlags.VALUE)'usuw. wartości liczb.
oCellRange.clearContents( com.sun.star.sheet.CellFlags.DATETIME)'usuw. daty i czasu
oCellRange.clearContents( com.sun.star.sheet.CellFlags.STRING)'usuw. tekstu
oCellRange.clearContents( com.sun.star.sheet.CellFlags.ANNOTATION)'usuw.komentarzy
oCellRange.clearContents( com.sun.star.sheet.CellFlags.FORMULA)'usuw. formuł
oCellRange.clearContents( com.sun.star.sheet.CellFlags.HARDATTR)'przywr.stand.formatu
oCellRange.clearContents( com.sun.star.sheet.CellFlags.STYLES)'przywr. stand.czcionki
oCellRange.clearContents( com.sun.star.sheet.CellFlags.OBJECTS)'usuw. obiektów
oCellRange.clearContents( com.sun.star.sheet.CellFlags.EDITATTR)'usuw. ????
End Sub
Wybieranie tekstu w arkuszu można wykonywać na kilka różnych sposobów przy okazji czynności związanych z zaznaczaniem komórek. Niektóre z nich, stosuje się często, a niektóre rzadziej.
Jak dotąd, przy automatyzowaniu zadań basic'em, nie byłem zmuszony do odróżniania tych pierwszych trzech przypadków. Bo jeżeli ja bądę mógł wpływać tylko na wielkość zakresu wybieranego tekstu (przypadek 2), to rozwiążę już właściwie cały problem czyli i pozostałe przypadki.
Poniżej jest przykład (procedura+funkcja), który pokazuje sposoby analizy zaznaczeń i sposób na pobranie tekstu z komórki oraz prezentację tych zdarzeń w MsgBox (Print). Tekst ten jest wyświetlany tylko wtedy, gdy była wybrana tylko jedna komórka.
'******************************************************************
Sub Main
Dim CzyWybranoTekst As Boolean
Dim oDokument As Object
oDokument = ThisComponent
CzyWybranoTekst = JestWybranyZadanyTekst (oDokument)'wywołanie poniższej funkcji
End Sub
'funkcja wywoływana z powyższej procedury jest wylistowana poniżej
Function JestWybranyZadanyTekst(oDoc As Object) As Boolean
Dim oSelections As Object, oSel As Object, oText As Object, oCursor As Object
REM JestWybranyZadanyTekst = False 'ten wiersz na razie nie jest istotny (pomijamy go)
If IsNull(oDoc) Then Exit Function 'zakończenie z powodu braku dokumentu
'Aktualne zaznaczenie w aktualnie czynnym dokumencie
oSelections = oDoc.getCurrentSelection()
If IsNull(oSelections) Then Exit Function 'zakończenie z powodu braku zaznaczenia
If oSelections.supportsService("com.sun.star.sheet.SheetCell") Then
Print "Zaznaczona jedna komórka = " & oSelections.getImplementationName()
MsgBox "znaleziono tekst = " & oSelections.getString()
ElseIf oSelections.supportsService("com.sun.star.sheet.SheetCellRange") Then
Print "Zaznaczono jeden jednolity obszar = " & oSelections.getImplementationName()
Print "nie wyświetlam żadnego zaznaczonego tekstu"
ElseIf oSelections.supportsService("com.sun.star.sheet.SheetCellRanges") Then
Print "Zaznaczono kilka oddzielnych obszarów = " & oSelections.getImplementationName()
MsgBox "Ilość oddzielnych obszarów = " & oSelections.getCount() & Chr(13) _
& "nie wyświetlam żadnego zaznaczonego tekstu"
Else
Print "Zaznaczono jakiś inny obiekt = " & oSelections.getImplementationName()
End If
End Function
'******************************************************************
Uwaga: Jeżeli będziecie kopiować powyższy kod to koniecznie obydwie części (procedurę i funkcję), bo procedura nic nie znaczy bez tej funkcji !
Najlepiej zacząć od przykładu pokazującego wywołanie okna dialogowego (które później będziemy nazywać krótko - dialogiem):
Dim oDlg As Object'deklaracja zmiennej o zasięgu wykraczającym po za jedną procedurę
Sub StartDialog
DialogLibraries.LoadLibrary("Standard")'bez tego wywołania nie da się skutecznie wywoływać nasze dialogi
oDlg = CreateUnoDialog(DialogLibraries.Standard.Dialog1 )
oDlg.execute()
End Sub
Konieczny jest komentarz, że jest tu wykorzystywana zmienna oDlg, której zasięg wykracza na zewnątrz metody, która ją wywołuje. Taką zmienną deklarujemy w początkowej sekcji modułu, przed główną procedurą (przed słowem kluczowym Sub !). Użycie takiej zmiennej jest konieczne ponieważ ten dialog będzie obsługiwany podczas działania innych podprogramów, włącznie z tymi, które są wywoływane zdarzeniami programów obsługi. Jeżeli te podprogramy mają mieć dostęp do naszego dialogu, to muszą być zdolne do takiego dostępu do zmiennej oDlg, który oznacza możliwość odwoływania się do niej.
Dialogi, podobnie biblioteki makr, mają określoną własną hierarchię. W powyższym przykładzie, wprowadzałem kod dla dialogu w następujący sposób. Wybrałem Tools->Macros, a potem kliknąłem na przycisk [Zarządzaj]. Zastałem tu sytuację taką, że ten potencjalny dialog został wykreowany pod ten dokument za pomocą sekcji Standard. Kiedy klikniemy na przycisk [Nowe okno dialogowe], to nazwa tego standardowego dialogu będzie określona domyślnie jako Dialog1. Ponieważ dialog ten jest uruchamiany z makra osadzonego w dokumencie, przyporządkowany jest według hierarchii dokumentów (Document's library hierarchy) do biblioteki DialogLibraries. Jeżeli potrzebujemy mieć dostęp do biblioteki hierarchii aplikacji z poziomu makra, w dokumencie musimy użyć biblioteki GlobalScope.DialogLibraries. Chodzi tu o to, aby określić się, czy decydujemy się na korzystanie z naszego okna dialogu tylko w tym dokumencie, czy chcemy mieć możliwość dostęp do niego z poziomu każdego otwieranego przez nas dokumentu (z pakietu OO).
Standardowa metoda na zamykanie okna dialogu zwija umieszczony wcześniej dialog, kiedy wystąpi wykonanie programu obsługi zamykającego ten dialog. Ja zwykle umieszczam na formatce przycisk [close], który przywołuje poniższy kod makra zamykającego okno.
Sub CloseDialog
oDlg.endExecute()
End Sub
Jeżeli potrzebujemy zamknąć ten dialog po określonym czasie, tworzymy nasz podprogram-opóźniacz zamykający dialog i powiązujemy go ze stosownym programem obsługi zdarzenia.
Sub CloseDialogAfterWaiting
wait(2000) 'oczekiwanie dwie sekundy(2tys milisekund)
oDlg.endExecute()
End Sub
Proszę wybaczyć tak wielką skrupulatność w podawaniu szczegółów, ale czuję, że to jest teraz bardzo potrzebne, bo właściwie to wszyscy są teraz początkującymi ! No więc, podczas gdy edytuję mój nowy dialog, klikam na przycisk control z tool-bar i wybieram przycisk polecenia. Jak już mam wstawiony ten przycisk, klikam prawym klawiszem myszki na tym przycisku i wybieram właściwości. Na zakładce Ogólne formularza właściwości, umieszczam nazwę tego klawisza np. ExitButton i Exit jako etykietkę (będzie widoczna na klawiszu). Przechodzę na zakładkę Wydarzenia, a następnie wybieram wiersz Podczas inicjowania i klikam na mały guzik [...], który służy do otwierania specjalnego dialogu, który pozwoli mi swobodnie przydzielić konkretne działania do zdarzenia. W sekcji Wydarzenia, wybieram Podczas inicjowania. W sekcji Makra, wybieram nasz podprogram zamykający CloseDialog, a następnie klikam na guzik Przypisz. Nasz przycisk Exit może być obsługiwany na dwa sposoby. Aktywować go można myszką albo klawiaturą. Możliwe jest stosowanie odmiennych podprogramów dla Klawisz naciśnięty albo Naciśnięto przycisk myszy ale teraz nie mam powódów do odróżniania.
| Tip | Musisz użyć zmienną dialogową tak, żeby jej zasięg wykraczał na zewnątrz podprogramu, tworząc możliwości do korzystania z niej przez inne podprogramy. |
| Tip | Gdy
wykorzystujemy bibliotekę DialogLibraries.Standard.Dialog1,
to oznacza odwołania do okna dialogowego w tym samym -
aktualnym dokumencie; Gdy wykorzystujemy bibliotekę GlobalScope.DialogLibraries.Standard.... to oznacza odwołania do globalnych okien dialogowych. |