Strona 1 z 1

Wartość bezwzględna z komórki

: śr gru 05, 2018 10:19 pm
autor: HKRWCK
Witam potrzebuję makra OO które z zaznaczonej komórki tworzy wartość bezwzględną (dodatnią z ujemnej).
Makro z Excel wygląda następująco:

ub Positive
Dim Cel As Range
For Each Cel In Selection
If IsNumeric(Cel.Value) Then
Cel.Value = Abs(Cel.Value)
End If
Next Cel
End Sub

Dziękuję za pomoc.

Re: Wartość bezwzględna z komórki

: śr gru 05, 2018 11:45 pm
autor: Jan_J
Andrew Pitonyak: Andrew Macro (http://www.pitonyak.org/AndrewMacro.odt) oraz OpenOffice Macros Explained (http://www.pitonyak.org/book/)
Warto czytać, zwłaszcza jeżeli jest to rodzaj zadania domowego (nie wiem czy jest).

A jeśli potrzebujesz nie do szkoły/na studia, tylko do własnej pracy: czy na pewno potrzebne jest aż makro? może wystarczy formuła (zwykła albo wektorowa) z użyciem funkcji abs / moduł.liczby?

Re: Wartość bezwzględna z komórki

: czw gru 06, 2018 9:17 am
autor: HKRWCK
Dzięki za odpowiedź. Potrzebuję do pracy, żeby sobie ją ułatwić. Chodzi o to że przycisk mam na wstążce, po którego przyciśnięciu zaznaczona wcześniej komórka zmienia się na dodatnią. Idealny byłby kod do wklejenia ;-)

Re: Wartość bezwzględna z komórki

: czw gru 06, 2018 12:05 pm
autor: Jan_J
No tak.
Załączam efekt smażenia. Ujmuje 3 przypadki: zaznaczone nic/pojedyncza komórka, albo blok komórek, albo zespół takich bloków.
W każdym z tych przypadków obiekt reprezentujący zaznaczenie ma w Calcu inny typ (A. Pitonyak, http://www.pitonyak.org/OOME_3_0.pdf, rozdział 15.4).
Testowałem wszystkie przypadki.

Wywołujemy tylko funkcję Positive().

Kod: Zaznacz cały

' rem cell: uchwyt obiektu komórki; obiekt modyfikowany jest in situ
sub absCell(cell)
  if cell.getType() = 1 then cell.setValue(abs(cell.getValue()))
end sub

' doc: uchwyt obiektu skoroszytu; adr: obiekt adresowy zakresu (to nie jest obiekt zaznaczenia!)
' modyfikacja obejmuje komórki z tego zakresu
sub absRange(doc, adr)
  sheet = doc.Sheets.getByIndex(adr.Sheet)
  for i = adr.startcolumn to adr.endcolumn
	  for j = adr.startrow to adr.endrow
	  	absCell(sheet.getCellbyPosition(i,j))
	  next j
  next i
end sub

' doc: uchwyt obiektu skoroszytu; rng: uchwyt obiektu złożonego zakresu (to nie jest adres ani lista adresów!)
' modyfikacja obejmuje komórki z wszystkich zakresów tego złożonego zakresu
sub absRanges(doc, rng)
  n = rng.count
  for i = 0 to n-1
    absRange(doc, rng.RangeAddresses(i))
  next i
end sub

' wywołujemy tylko to
sub Positive()
	dim doc as object
	dim sel as object
	doc = thisComponent
	sel = doc.CurrentController.getSelection()
	if sel.supportsService("com.sun.star.sheet.SheetCell") then
	  absCell(sel)
	elseif sel.supportsService("com.sun.star.sheet.SheetCellRange") then
	  absRange(doc, sel.getRangeAddress())
	else rem sel.supportsService("com.sun.star.sheet.SheetCellRanges")
	  absRanges(doc, sel)
	end if
end sub
W VBA Excela wygląda krócej, z kilku powodów:
* Excel udostępnia globalnie całą masę obiektów reprezentujących stan aplikacji. W Calcu jest większy porządek, m.in. aplikacja (Calc, np. zaznaczenie) jest odseparowana od danych (arkusze, komórki), a liczba zmiennych domyślnie dostępnych globalnie jest ograniczona.
* Excel pozwala unikać unikać jawnych pętli po zakresach tablic, na korzyść składni wektorowej albo pętli typu `for each` (płaska lista, a nie indeksowana tablica).
W Calcu też jest pętla `for each` i jakieś elementy wektoryzacji, ale ich nie znam zbyt dobrze. Tu jest jakaś szansa na usprawnienie. Na przykład, funkcję dla zespołu bloków da się przepisać do postaci

Kod: Zaznacz cały

sub absRanges(doc, rng)
	for each adr in rng.RangeAddresses
	  absRange(doc, adr)
	next adr
end sub
ale czy są gotowe środki, by zrobić podobnie pojedynczą pętlę `for each` dla trawersu wielopoziomowej/wielowymiarowej struktury komórka po komórce, to nie wiem.

Re: Wartość bezwzględna z komórki

: czw gru 06, 2018 10:03 pm
autor: HKRWCK
Dziękuję za podjęcie tematu jednak po uruchomieniu makra wyskakuje komunikat jak poniżej

Wystąpił błąd modułu Scripting Framework podczas wykonywania w języku Basic skryptu Standard.Module1.absRanges.
Wrong number of parameters!

Re: Wartość bezwzględna z komórki

: czw gru 06, 2018 10:41 pm
autor: Jan_J
Wywoływać należy tylko procedurę Positive().

Pozostałe makra są używane do realizacji czynności w szczególnych sytuacjach, tak by nie pisać analogicznego kodu wielokrotnie. Muszą one mieć podane parametry, które trzeba przygotować programowo. Przy próbie wywołania z przycisku albo formularza będą generować błąd, bo parametrów im nie przekazano.
Można by im nadać atrybut private, wtedy nie byłyby widoczne z zewnątrz modułu, ale o takie szczegóły nie dbam w szkicu.

Sprawdzałem poprawność działania na LibreOffice Calc 6.0 (Windows 10) oraz 5.3 (OpenSUSE).
Nie sądzę, by obsługa zaznaczeń w Apache OpenOffice była inna; gdyby tak było, raczej wiedziałbym o tym.

Re: Wartość bezwzględna z komórki

: pt gru 07, 2018 9:23 pm
autor: HKRWCK
Witam,
Niestety używając funkcji Positive również nie działa mi kod makra. Jeżeli można to proszę o umieszczenie gotowego kodu w załączonym pliku. :?:
Będę wdzięczny.
Pozdrawiam.

Re: Wartość bezwzględna z komórki

: pt gru 07, 2018 10:32 pm
autor: Jan_J
Wpięte, w załączeniu.
grudzien - roboczo - 2018.12.04.ods
(17.86 KiB) Pobrany 191 razy
W kolumnie i arkusza "grudzień_2018" makro nie zadziała, bo tam nie leżą dane liczbowe, tylko wyniki obliczeń przez formuły.
W innych miejscach działa, sprawdzałem wpisując liczby ujemne w różne miejsca.

W makrze (konkretnie w funkcji absCell) jest umieszczony warunek: jeżeli zawartość komórki jest typu liczbowego, to nałóż na nią moduł.
Formuła to inny przypadek. Można się pozbyć warunku, ale wtedy stracisz związki między danymi a wynikami. Głupio.
Lepiej napisać w formule =moduł.liczby(czegoś_co_się_wylicza_a_co_może_być_ujemne).
Dlatego pytałem: czy nie lepiej formułą. Moim zdaniem, jeśli chcemy urwać minus z obliczeń dawanych przez formułę, to tylko formułą.
Jaką konkretnie decyzję podjąć? to zależy od logiki Twoich obliczeń. Żeby sobie pomóc, a nie nabałaganić.

Re: Wartość bezwzględna z komórki

: pt gru 07, 2018 10:38 pm
autor: HKRWCK
Czy nie można oderwać obliczeń danej formuły z liczbą ujemną i zastąpić ją modułem?

Re: Wartość bezwzględna z komórki

: pt gru 07, 2018 10:49 pm
autor: Jan_J
// sorry, użyłem [edit] zamiast [reply]; poprawiam się ;;

Można. Taki wariant

Kod: Zaznacz cały

sub absCell(cell)
  cell.setValue(abs(cell.getValue()))
end sub
tak zrobi. Zyskasz dodatniość, stracisz formułę. Zaś próba wywołania na komórce z tekstem spowoduje wpisanie zera i utratę tekstu.

O wiele mądrzej jest zmienić formułę obliczającą. Zamiast

Kod: Zaznacz cały

=bla bla bla
użyć

Kod: Zaznacz cały

=moduł.liczby(bla bla bla)
o tym pisałem na początku, a i wyżej także. No i policzy się wtedy `samo`, bez wciskania przycisku.

Re: Wartość bezwzględna z komórki

: pt gru 07, 2018 10:58 pm
autor: HKRWCK
Możesz mi to wrzucić w plik?

Re: Wartość bezwzględna z komórki

: pt gru 07, 2018 11:22 pm
autor: Jan_J
To nie jest programowanie, w sensie znajomości języka proceduralnego, tylko zwykła obsługa arkusza kalkulacyjnego.
Jeżeli zmodyfikujesz sobie formułę w kolumnie i wg mojego opisu, to będziesz mieć w niej same nieujemne wyniki, z formuł.
Z tym że ja nie wezmę odpowiedzialności za zgodność mojej propozycji z Twoim zamiarem.

Re: Wartość bezwzględna z komórki

: pt gru 07, 2018 11:36 pm
autor: HKRWCK
Chodzi mi o to że wartości ujemne są wpisywane wcześniej bo to zaległości klientów, natomiast powiedzmy na dzień dzisiejszy po wpłacie klienta wartość w komórce powinna być na +. Pomysł jest taki aby zaznaczoną komórkę przekształcało makro.

Re: Wartość bezwzględna z komórki

: sob gru 08, 2018 10:39 am
autor: Jan_J
Jeżeli wpłata jest rejestrowana w komórce, to wystarczy ją odjąć od zadłużenia. Sposób trochę zależy od organizacji danych, jeżeli rejestracja wpłat jest w osobnych kolumnach w kolejności ich dokonywania, to może wymagać wyszukania wpisu w tabeli (wyszukaj.pionowo).

Nie rozumiem dlaczego fakt dokonania wpłaty zmienia zadłużenie (np. -120) na wartość dodatnią (odp. 120) a nie na 0.
Ale może tak ma być, nie znam logiki tych obliczeń.