Funkcja wyodrębnij fragmenty ciągu. (nowsza wersja)

Gotowe szablony, skrypty, makropolecenia i rozszerzenia. Tutaj możesz pochwalić i podzielić się swoją twórczością z innymi użytkownikami
Awatar użytkownika
Jermor
Posty: 2239
Rejestracja: sob paź 12, 2013 11:09 am
Kontakt:

Funkcja wyodrębnij fragmenty ciągu. (nowsza wersja)

Post autor: Jermor »

Dodana nowa wersja funkcji (z nowymi parametrami)
W dziale Calc na forum pojawiła się prośba o rozwiązanie problemu wyodrębnienia z zadanego ciągu tekstowego wszystkich fragmentów tekstowych zawartych między zdefiniowanymi znakami i połączenie ich w jeden ciąg rozdzielony wybranym separatorem. W tym konkretnym przypadku chodziło o wyodrębnienie wszystkich liczb zawartych między znacznikami "<id>" oraz "</id>".
Oto przykład takiego ciągu:
<id>550124</id><guid>238974shdbf23874dgf23hr</guid><id>550125</id><guid>238974shdbf23874dgf23hr</guid><id>550126</id><guid>238974shdbf23874dgf23hr</guid><id>5503454</id> <guid>238974shdbf23874dgf23hr</guid><id>550456</id> <guid>238974shdbf23874dgf23hr</guid><id>550456</id><guid>238974shdbf23874dgf23hr</guid>
Odpowiadając pytającemu, napisałem funkcję użytkownika, którą można zastosować we własnym arkuszu. Funkcję tę nazwałem LICZBY, gdyż chodziło o wyodrębnienie liczb. Po zastanowieniu pomyślałem, że taka funkcja może przydać się jeszcze komuś, więc nieco ją zmodyfikowałem, zmieniłem nazwę na EKSTRAKT i załączam zainteresowanym do ewentualnego wykorzystania.
EKSTRAKT
Zwraca ciąg złożony z wyodrębnionych fragmentów tekstowych, znajdujących się między zdefiniowanymi znakami wyróżniającymi, wewnątrz innego dłuższego tekstu. Fragmenty te są rozdzielone separatorami wskazanymi przez uzytkownika.
Składnia

Kod: Zaznacz cały

EKSTRAKT(tekst;przed;za;separator)
Tekst jest przeszukiwanym ciągiem lub adresem komórki zawierającej taki ciąg.
Przed jest ciągiem poprzedzającym szukany fragment albo adresem komórki zawierającym taki ciąg.
Za jest ciągiem kończącym szukany fragment albo adresem komórki zawierającym taki ciąg.
Separator jest ciągiem rozdzielającym znalezione fragmenty albo adresem komórki zawierającym taki ciąg. Parametr może być pominięty i wtedy separatorem będzie znak spacji.
Uwaga dotycząca pominiętych parametrów.
Z punktu widzenia funkcji parametrem pominiętym jest ten, przed którym nie wystąpił poprzedzający go średnik. W tej sytuacji jako pominięty traktowany może być tylko ostatni ze wszystkich parametrów bo tylko wtedy, pomijając go, możemy pominąć poprzedzający go średnik. Inne choć zasygnalizowane tylko średnikiem, nie są parametrami pominiętymi i są przekazywane do funkcji jako wartość zerowa. Zatem gdy zostanie postawiony średnik poprzedzający ostatni parametr, a sam parametr nie zostanie podany, i tak przekazana zostanie wartość zerowa. Dlatego jeśli parametr Separator miałby nie zostać podany, ale zostanie postawiony średnik go sygnalizujący, należy podać jakąś jego postać, choćby pusty ciąg złożony z dwóch kolejnych znaków cudzysłowu.

Funkcja wymaga, aby ciągi Przed i Za się różniły. Jeśli tak nie będzie, zostanie zwrócona wartość: "Ciągi PRZED i ZA nie mogą być takie same". Jeżeli ciąg Przed nie wystąpi w tekście, zwrócona zostanie wartość: "Brak ciągu PRZED". Jeżeli po zapisie Przed w tekście nie wystąpi zapis Za, zwróconym fragmentem tekstowym będzie fragment od ciągu Przed do końca tekstu.
Przykład:

Kod: Zaznacz cały

=EKSTRAKT(A2;"<id>";"</id>")
Jeżeli w A2 znajdzie się tekst wymieniony jako przykład, zwrócona zostanie wartość tekstowa: 550124 550125 550126 5503454 550456 550456.
Fragmenty rozdzielone są spacją, ze względu na brak czwartego parametru.

Kod: Zaznacz cały

=EKSTRAKT(A2;B2;B3;B4)
Jeśli B2 i B3 zawierają wyżej zastosowane ciągi a B4 zawiera ciąg "+^+" to wynikiem funkcji będzie ciąg: 550124+^+550125+^+550126+^+5503454+^+550456+^+550456.

Funkcję należy przekopiować do biblioteki "Standard" w kontenerze makr dokumentu Calc, wówczas będzie dostępna tylko w tym dokumencie, albo umieścić ją w bibliotece "Standard" kontenera "Moje makra", wówczas będzie dostępna we wszystkich arkuszach.
Funkcja EKSTRAKT.

Kod: Zaznacz cały

Function ekstrakt(tekst,przed,za, optional separator) as string
REM Funkcja z ciągu tekstowego "tekst" wyodrebnia wszystkie teksty
REM znajdujące sie między ciagami "przed" i "za" i łączy je w jeden
REM nowy ciąg rozdzielając je ciągiem podanym jako "separator".
REM Autor: Jermor, polskie forum Apache OpenOffice i LibreOffice. (2019)
dim t as string
dim pos1 as long, pos2 as long
rem pos1 wyznacza położenie ciągu "przed", pos2 położenie ciągu "za"
dim i as integer,j as integer
if IsMissing(separator) then separator=" "
pos1=1 : pos2=1
t=""
pos1=InStr(pos1,tekst,przed)
if pos1=0 then
	ekstrakt="Brak ciągu PRZED"
	exit Function ' ciąg "przed" w ogóle nie wystepuje w tekście
End If
If przed=za then
	ekstrakt="Ciągi PRZED i ZA nie mogą być takie same"
	exit Function
End If
i=len(przed) 'zawiera długośc ciagu "przed"
j=len(za)
do
	pos2=InStr(pos1,tekst,za)
	t=t &  mid(tekst,pos1+i,pos2-pos1-i) & separator
	if pos2=0 then exit do
	pos1=InStr(pos2+j,tekst,przed)
loop while pos1<>0
ekstrakt=left(t,len(t)-len(separator))
End Function
Jeden z forumowiczów zgłosił prośbę o zmodyfikowanie możliwości funkcji. Dodałem do niej możliwość podania dwóch dodatkowych parametrów.
Nowa składnia wygląda tak:
Składnia

Kod: Zaznacz cały

EKSTRAKT(tekst;przed;za;separator;pierwszy;ile)
Parametr pierwszy jest liczbą całkowitą i informuje, który ze znalezionych ciągów ma zostać zwrócony jako pierwszy. Jeśli zostanie pominięty zostanie wybrany pierwszy ciąg. Jeśli podano liczbę większą niż ilość ciągów w tekście, zwrócony zostanie ciąg pusty
Parametr ile jest liczbą całkowitą i informuje ile ciągów ma zostać zwróconych. Jeśli zostanie pominięty przyjmuje się, że wszystkie do końca tekstu.
Nowa wersja kodu poniżej.

Kod: Zaznacz cały

Function ekstrakt(tekst,przed,za, optional separator, optional pierwszy, optional ile) as string
On Local Error goto niemanic
REM Funkcja z ciągu tekstowego "tekst" wyodrebnia wszystkie teksty
REM znajdujące sie między ciagami "przed" i "za" i łączy je w jeden
REM nowy ciąg rozdzielając je ciągiem podanym jako "separator".
REM Autor: Jermor, polskie forum Apache OpenOffice i LibreOffice. (2019)
dim t as string
dim pos1 as long, pos2 as long
rem pos1 wyznacza położenie ciągu "przed", pos2 położenie ciągu "za"
dim i as integer,j as integer, k as integer
if IsMissing(separator) then separator=" "
if isMissing(pierwszy) or not isNumeric(pierwszy) or pierwszy=0 then pierwszy=1
if isMissing(ile) or not isNumeric(ile) then ile=0
pierwszy=int(abs(pierwszy)) : ile= int(abs(ile))
pos1=1 : pos2=1
t="" : k=1
pos1=InStr(pos1,tekst,przed)
if pos1=0 then
   ekstrakt="Brak ciągu PRZED"
   exit Function ' ciąg "przed" w ogóle nie wystepuje w tekście
End If
If przed=za then
   ekstrakt="Ciągi PRZED i ZA nie mogą być takie same"
   exit Function
End If
i=len(przed) 'zawiera długośc ciagu "przed"
j=len(za)
do
   pos2=InStr(pos1,tekst,za)
   If k>=pierwszy and k<=iif(ile=0,k+1,pierwszy+ile-1) then   t=t &  mid(tekst,pos1+i,pos2-pos1-i) & separator
   k=k+1
   if pos2=0 then exit do
   pos1=InStr(pos2+j,tekst,przed)
loop while pos1<>0
ekstrakt=left(t,len(t)-len(separator))
Exit Function
niemanic:
On Local Error goto 0
ekstrakt=""
End Function
AOO 4.1.15, LO 7.5.9 (x64) na Windows 10 64bit
Ważne!
Jeśli twój problem został rozwiązany, wróć do swojego pierwszego postu, przejdź do edycji i dopisz [SOLVED] w temacie.
Inni, którzy mają podobny problem, będą wiedzieli, że istnieje jego rozwiązanie.
Dawidek990
Posty: 58
Rejestracja: czw gru 13, 2018 12:15 am

Re: Funkcja wyodrębnij fragmenty ciągu. (nowsza wersja)

Post autor: Dawidek990 »

A powiedz mi, dalo by sie tak zrobic zeby formula wykrywala np drugie w komorce wystepujece slowo jako poczatek, i np czwarte wystepujace slowo jako koniec?
np ekstrakt(a1;"mleko"(ale to ktore wystepuje jako 2 w komorce nie pierwsze);"koniec"(ale np w komorce wystepuja 4 slowa koniec, i zeby znalazl to trzecie np) )
czesto czegos takiego potrzebuje, zeby wyciagnal mi tekst do ktoregos tam slowa ktore wystepuje w tekscie, a nie koniecznie pierwszego ktore znajdzie.
OpenOffice 4.1.6 Windows 10
ODPOWIEDZ