Import danych > Import specjalny (format 3.0) > Definiowanie formatu plików

Drukuj

Definiowanie formatu plików

Informacje ogólne

Import specjalny obsługuje dane w różnorodnych formatach. Razem z programem dostarczanych jest wiele definicji popularnych formatów danych, które mogą być używane natychmiast. Dodatkowo użytkownik ma możliwość zdefiniowania (opisania) innego, własnego formatu danych. Dzięki temu używając standardowego programu FK można zdefiniować taki szablon, który wczyta dane z innego programu bez konieczności dokonywania kosztownych i czasochłonnych zmian w obydwu programach. Istnieje oczywiście kilka założeń, które muszą być spełnione, aby dane dały się opisać własną definicją formatu:

Plik danych musi być w formacie tekstowym (plik ASCII).

Oddzielne pliki nie mogą zawierać danych powiązanych relacyjnie za sobą, np. jeden plik zawiera nagłówki dokumentów, drugi zapisy księgowe, a trzeci rejestry VAT lub rozrachunki.

Wyjątkiem od tej reguły są kartoteki, które mogą być umieszczane w innych plikach niż dokumenty księgowe.

Format jednego pliku powinien być jednorodny (tzn. nie może być jednych danych w formacie CDF, a innych w formacie SDF)    

Musi istnieć jednoznaczny sposób opisania podstawowych elementów formatu, czyli:

początku sekcji

końca sekcji

nazwy pola (o ile występuje)

wartości pola

komentarzy (o ile występują)

 

Do opisu elementów formatu wykorzystano tzw. wyrażenia regularne, czyli pewien sposób opisu właściwości analizowanego tekstu, tak aby opisać jego cechy a nie konkretną wartość.  Najprostszymi wyrażeniami regularnymi były znaki typu *(dowolny ciąg znaków) oraz ? (dowolny jeden znak) używane w systemie DOS do określenia grupy plików.

Dzięki rozbudowanemu mechanizmowi wyszukiwania niejednoznacznego można tworzyć nawet bardzo skomplikowane opisy, w stylu:

 

Pole danych składa się z tekstu umieszczonego w parze nawiasów trójkątnych, przy czym nazwą pola jest tekst do znaku dwukropka, a wartością jest tekst po znaku dwukropka, przy czym dodatkowo mają być ignorowane (nie są danymi)wszystkie białe znaki pomiędzy znakiem dwukropka a zamykającym nawiasem.

 

Co odpowiada przykładowym danym:

<kwota:   143765,84   >

<czas:12:28.56> 

 

i opisywane jest wyrażeniem

<{*}/::b{*}:b>

 

Pełny opis wyrażeń regularnych można znaleźć w pliku pomocy do języka raportów (AMBASFK.CHM), który dostarczany jest standardowo wraz z programem Finanse i Księgowość.

Pomimo niewielu elementów składających się na definicję formatu, opisywanie własnych formatów danych  wymaga sporej wiedzy i często pomysłowości. Można w firmie Symfonia sp. z o.o. zamówić płatną usługę tego rodzaju.

 

Elementy opisu formatu

Sekcja

Sekcja jest elementarną porcją informacji, wczytywanej i przetwarzanej jako całość. W zależności od formatu może to być jedna linia w pliku (format CDF lub  SDF) , albo też kilka kolejnych linii (np. format AMS).  Do prawidłowego podzielenia pliku wejściowego na sekcje (czyli np. kolejne dokumenty) należy opisać w jaki sposób rozpoznawany będzie początek sekcji oraz w jaki sposób rozpoznawany będzie koniec sekcji.

W najprostszym przypadku, dla formatu SDF lub CDF:

początkiem sekcji jest początek linii, opisuje to wyrażenie ^

końcem sekcji koniec linii, opisuje to wyrażenie $

Dla bardziej skomplikowanego przypadku AMS

początkiem sekcji jest dowolna nazwa po której występuje otwierający nawias klamrowy, opisuje to wyrażenie ^[ \t]#{*}[ \t]#/{*$-

końcem sekcji jest zamykający nawias klamrowy, opisuje to wyrażenie ^*/}*$-

Każdy opis własnego formatu musi mieć zdefiniowany opis początku i końca sekcji.

Przy definiowaniu początku sekcji należy zwrócić uwagę na dwa elementy, mianowicie nazwę sekcji, którą będzie wyrażenie znajdujące się wewnątrz nawiasów klamrowych w wyrażeniu opisującym początek sekcji. Oczywiście wyrażenie to występuje tylko dla formatów zawierających jawnie nazwę sekcji.

Przykładowo jeśli plik zawiera pola oddzielone średnikami, a pierwsze pole zawiera symbol wyróżniający typ danych, np. typ dokumentu:

FAKTURA; 0; 123,56; 22; „Sprzedaż towarów”

KASA; 0; 5857,54; 201-1-1285; „Zapłata za fakturę”

 

W takim wypadku możemy stworzyć sekcje wejściowe o różnych nazwach, opisując początek sekcji następująco:

^{*};-

co oznacza, że nazwą sekcji będzie wartość pierwszego pola, czyli dowolny ciąg znaków od początku linii do pierwszego średnika.

Drugim ważnym elementem wyrażenia regularnego jest znak – (minus), który określa, od którego miejsca w analizowanej linii wejściowej ma być kontynuowane poszukiwanie następnych elementów pliku (podsekcji oraz pól)

W powyższym przykładzie następną analizowaną informacją w linii będzie ciąg znaków po pierwszym średniku (minus jest po średniku). Znak minus może być umieszczony w dowolnym miejscu wyrażenia, stosownie do potrzeb. Jeśli np. chcielibyśmy pominąć drugie kolejne pole (w przykładzie ma wartość 0), to można byłoby zapisać

^{*};*;-

a jeśli nazwą miałyby być tylko dwie pierwsze litery z pierwszego pola, a reszta tego pola już daną (może nie ma to wielkiego sensu, ale dobrze ilustruje działanie minusa!), zapisalibyśmy:

^{??}-*;

W specyfikacji końca sekcji nie ma już potrzeby oznaczania nazwy sekcji i całe wyrażenie służy tylko identyfikacji końca sekcji. Definicja końca sekcji w pliku danych nie musi być związana z końcem linii, nawet jeśli rzeczywiście jedna linia zawiera jedną sekcję. Przykładem może być format AM, w którym znakiem końca sekcji jest znalezienie początku nowej sekcji lub słowa koniec.

Tak może wyglądać przykładowy plik danych

„DOK”; 1; 1998-12-03 

„VAT”; 2746,56; 0; 22; A

„DOK”; 2; 1998-12-04 

„VAT”; 2746,56; 0; 22; A

Koniec.

 

Linia zawierająca na początku „DOK” jest sekcją dokumentu, a kolejna linia „VAT” jest jej podsekcją.

 

Definicja końca sekcji dokumentu wygląda następująco:

(^-"{DOK}")|(^#Koniec.-)

mamy tu aż dwa minusy!

Jeśli w pliku danych zostanie odnaleziony tekst „DOK”, to oczywiście zakończy to poprzednią sekcję dokumentu, ale znak minus jest przed „DOK”, więc ten tekst nie zostanie „zjedzony” jako znak końca sekcji, tylko pozostanie do dalszej analizy i zostanie rozpoznany jako początek nowej sekcji. Trochę inaczej będzie jeśli zostanie rozpoznane słowo Koniec. W tym przypadku minus jest na końcu tego słowa, więc zostanie ono pominięte i nie będzie już dalej analizowane.

 

Wartości

Dane zawarte w pliku danych zostały umownie podzielone na dwie kategorie: „dane liczbowe” oraz „dane tekstowe”. W zasadzie rozsądniejszym podziałem mogło być „dane w cudzysłowie” oraz dane „dane bez cudzysłowu”, bo de facto do tego sprowadza się ten podział.

 

Pod nazwą dane liczbowe ukrywają się wszystkie dane, które nie są umieszczane w cudzysłowie, czyli:

liczby

daty

kwoty

numery nip

kody pocztowe

teksty, które nie zostały podane w cudzysłowie

Natomiast „dane tekstowe” oznaczają teksty umieszczone wewnątrz znaków cudzysłowu. Rozróżnienie typów danych ma na celu tylko i wyłącznie usunięcie znaków cudzysłowu podczas wczytywania danych tak, aby pole wejściowe dla szablonu zawierało tylko „czyste” dane.

Należy pamiętać, że dla szablonu wszystkie dane z pliku wejściowego są tekstami, niezależnie czy są umieszczone w cudzysłowie, czy też nie. Ponieważ opis wartości numerycznej i tekstowej jest dokonywany poprzez wyrażenia regularne, mówiąc „cudzysłów” mam na myśli dowolne znaki znajdujące się na początku i końcu tekstu. Mogą to być znaki cudzysłowu „”, apostrofów ‘’ lub dowolne inne, np. nawiasów, prefiksów itd.

 

Przykładowe pola w formacie SDF:

"Zakup towarów";1999-12-28;7376,46; "Holding S.A."

 

Definicja wartości numerycznej

^|;{*}-;|$

którą należałoby czytać:

wartość numeryczna zaczyna się od początku linii lub od znaku średnika, po którym następuje właściwa wartość będąca dowolnym ciągiem znaków o długości 0 lub większej, zakończona średnikiem lub znakiem końca linii.

 

Definicja wartości tekstowej

^|;"{*}"-;|$

którą należałoby czytać:

wartość tekstowa zaczyna się od początku linii lub od znaku średnika, po którym następuje znak cudzysłowu (pomijanego) oraz właściwa wartość będąca dowolnym ciągiem znaków o długości 0 lub większej, zakończona znakiem cudzysłowu(pomijanym) oraz  średnikiem lub znakiem końca linii.

 

Jak widać w obydwu przykładach znak minus znajduje się przed średnikiem kończącym pole, tak więc analiza następnego pola rozpocznie się od znaku średnika, co spełni warunek początkowy dla następnej definicji pola (pierwsze pole zaczyna się od początku linii, kolejne pole zaczyna się od średnika). Bardziej złożonym przykładem jest wartość z nazwą pola

Nazwa kontrahenta =  „Holding S.A.”

 

Oraz opis tego pola:

/=:b"{*}":b $-

który należy czytać:

wartość tekstowa zaczyna się po znaku równości, po którym może znajdować się dowolna ilość białych znaków. Zaczyna się znakiem  cudzysłowu (pomijanym). Jest ona dowolnym ciągiem znaków o długości 0 lub większej, zakończona znakiem cudzysłowu(pomijanym) po którym mogą  znajdować się do końca linii  tylko białe znaki (spacje, tabulatory etc.)

 

Nazwy pól

Dla formatów z nazwą pola można określić nazwę pola, którą później będzie można używać w szablonie do identyfikacji danych. Nie jest to wymóg konieczny i można do pól odwoływać się poprzez ich numer kolejny, ale zwykle w formatach z nazwami pól kolejność pól nie jest sztywno ustalona i może ulec zmianie. Jest to jedna z zalet formatu z nazwami pól. Nazwy pól opisuje się analogicznie jak wartości pól, ale w tym przypadku nie ma rozróżnienia pomiędzy polami numerycznymi i tekstowymi.

 

Przykład  

Nazwa kontrahenta =  „Holding S.A.” 

Oraz opis nazwy pola

^:b{*}:b-/=

 

Co oznacza:

Nazwa pola zaczyna się od początku linii, z pominięciem początkowych białych znaków. Jest to ciąg dowolnych znaków o długości 0 lub więcej znaków, po których występuje dowolna ilość białych znaków (pomijanych) i znak równości.

 

Warto zwrócić uwagę na położenie znaku minus, który znajduje się przed znakiem równości i powoduje to, że analiza dalszej części linii będzie kontynuowana od znaku równości razem z tym znakiem – porównaj z definicją wartości tekstowej dla pól z nazwami: zaczyna się od znaku równości.

 

Komentarze

W pliku danych mogą znajdować się linie, które nie zawierają istotnych informacji dla importu danych, a tylko uwagi i komentarze przeznaczone dla osób które będą przeglądać plik danych. Zwykle uwagi takie nie spełniają wymagań co do formatu właściwych danych i naruszają w pewien sposób strukturę pliku. W każdym razie nie można ich potraktować i wczytać jako dane, a odrzucić w szablonie jako dane nieistotne. Muszą one zostać zidentyfikowane i odrzucone już na etapie analizy formatu pliku. Służy temu definicja (opisy) komentarza.

 

Przykład komentarza liniowego dla formatu SDF (znakiem komentarza jest średnik na początku linii):

;to jest komentarz w pliku SDF, ta linia zostanie zignorowana. Następna linia również 

;RK;”Zapłata za fakturę”;12387,98;22;201-1;1999-12-30

Oraz bardzo prosta definicja tego komentarza:

^;

średnik znajdujący się na początku linii

 

Przykład komentarza liniowego w formacie AMS, tworzą go dwa znaki ukośnika //

 

//komentarz w formacie AMS, kolejna linia też zawiera komentarz po polu danych

kwota = 876,98   //bez podatku VAT

Oraz definicja tego komentarza:

////*

Dowolny ciąg  znaków po dwóch znakach ukośnika

 

Proszę zwrócić uwagę, że w definicji tego komentarza znajdują się cztery ukośniki. Wynika to z faktu, że ukośnik ma specjalne znaczenie w wyrażeniach regularnych, i aby zaznaczyć, że chodzi nam o pojedynczy znak ukośnika a nie specjalne znaczenie ukośnika w wyrażeniach regularnych, musimy wpisać dwa ukośniki.

Komentarz liniowy zawsze obowiązuje od początku komentarza do końca linii.

 

Pliki polimorficzne

Często bywa tak, że jeden plik danych zawiera informacje różnego rodzaju, zapisane w trochę różny sposób.  Przykładowo w pliku o formacie SDF część linii zawiera informację o dokumentach księgowych, a część o kontrahencie. Przykładem jest format AM, w którym jedna linia SDF zawiera dane dokumentu, a kolejne linie dane zapisów księgowych, rejestrów VAT i rozrachunków. W takich przypadkach należy zdefiniować kilka kolejnych opisów różnych sekcji (początku i końca sekcji, formatu danych itd.).  Każdy taki komplet danych opisuje jeden rodzaj sekcji wejściowych. W każdej sekcji mogą być dane w innym formacie, przykładem jest format POLKA, który w jednym rodzaju sekcji ma nazwy pól oddzielone dwukropkiem, a w innej oddzielone znakiem równości.

 

Kolejność analizowania elementów formatu

Do pełnego zrozumienia zasad definiowania własnych formatów danych niezbędna jest znajomość reguł rządzących analizą pliku wejściowego.  W poprzednich punktach opisane zostały zasady rozpoznawania poszczególnych elementów pliku wejściowego, teraz omówię kolejność w jakiej poszczególne elementy są analizowane.

Plik danych jest analizowany linia po linii. Jako linię rozumie się ciąg znaków ASCII do znaku końca linii, czyli CR LF (kody 10 oraz 13).

pierwszą sprawdzaną rzeczą jest komentarz. Jeśli zostanie odnaleziony  wówczas cała linia do końca jest ignorowana i wczytywana jest następna linia z pliku danych.

Sprawdzany jest początek sekcji. Jeśli definicja formatu  zawiera więcej niż jedną definicję sekcji, wówczas sprawdzane są kolejno wszystkie definicje aż do napotkania pierwszej zgodnej definicji.

Jeśli natrafiono na początek sekcji, to tworzona jest sekcja wejściowa.

Po zidentyfikowaniu początku sekcji następnym sprawdzanym elementem jest koniec sekcji.

Jeśli nie ma końca sekcji, to sprawdzany jest początek następnej sekcji (podsekcji). Jeśli znaleziono początek sekcji to tworzona jest podsekcja sekcji wejściowej i analiza powraca do punktu  2.1.1

Jeśli natrafiono na koniec sekcji (komplementarny do ostatnio znalezionego początku sekcji) to zamykana jest podsekcja wejściowa i przechodzimy do punktu 3

wczytywane jest pole danych, używając definicji pól zgodnej z ostatnio odnalezioną sekcją. Dane są umieszczane w ostatniej otwartej sekcji (podsekcji) wejściowej

wracamy do punktu 1.

Powyższa kolejność jest zachowana dla wszystkich formatów predefiniowanych oraz dla formatów własnych użytkownika.

 

Definiowanie formatu w pliku IMPEXP.INI

W pliku IMPEXP.INI, znajdującym się w katalogu instalacyjnym programu Finanse i Księgowość, można zdefiniować własne, dodatkowe formaty pliku wejściowego. Struktura tego pliku jest analogiczna jak innych typowych plików INI w systemie Windows (np. pliku WIN.INI), czyli zawiera nazwane sekcje, zawierające nazwane wejścia z określoną wartością.  Pierwszą istotną sekcją w pliku IMPEXP.INI jest sekcja _RD_FORMAT, mająca następującą postać:

 

[_RD_FORMAT]

SDF=1

AM=2

POLKA=2

AMS=1

INI=1

COMMA=1

SUBIEKT=3

 

Każde wejście w tej sekcji składa się z nazwy formatu oraz po znaku równości liczby właściwych sekcji opisujących format pliku. Aby dodać własny format, należy dodać w tej sekcji nazwę kolejnego formatu i liczbę jego podsekcji definiujących. Właściwy opis Formatu znajduje się w sekcjach opisu. Zasady tworzenia tych sekcji są następujące:  nazwę sekcji definiującej budujemy dodając przed nazwą formatu człon _RD_FORMAT, a po nazwie formatu znak podkreślenia oraz numer kolejny sekcji w ramach tego formatu.

W poniższym przykładzie podano sekcje definiujące dla formatu SDF

 

[_RD_FORMAT_SDF_0]

; komentarze, zmienne globalne i  ustawienia translatora

KOM_LIN_POCZ=(^;)|(^Koniec.)

 

[_RD_FORMAT_SDF_1]

; opis sekcji musi zawierać początek i koniec sekcji oraz definicje pól

SEKCJA_POCZATEK=^-{*}[~ \t]

SEKCJA_KONIEC=$                        

WARTOSC_LICZBOWA=^|;{*}-;|$

WARTOSC_TEKSTOWA=^|;"{*}"[ \t]#-;|$

 

Sekcja o numerze 0 jest zarezerwowana dla opisu komentarzy, zmiennych globalnych oraz ustawień translatora.

Kolejne sekcje, o numerach od 1 aż do  numeru podanego w sekcji definicji nazwy formatu zawierają opis kolejnych formatów sekcji, w kolejności ich analizowania podczas wczytywania pliku wejściowego

Przykładowo chcemy utworzyć dodatkowy format pliku o następującej postaci:

 

<sekcja>

 <pole=wartość>

 <pole2=wartość2>

</sekcja>

<REM> wszystko po słowie rem w nawiasach jest komentarzem

 

Dopisujemy nową nazwę formatu o nazwie NOWY

[_RD_FORMAT]

SDF=1

AM=2

POLKA=2

AMS=1

INI=1

COMMA=1

SUBIEKT=3

NOWY=1

 

Oraz tworzymy sekcje definiujące:

[_RD_FORMAT_NOWY_0]

; komentarze, zmienne globalne i  ustawienia translatora

KOM_LIN_POCZ=<REM>

 

[_RD_FORMAT_NOWY_1]

; opis sekcji musi zawierać początek i koniec sekcji oraz definicje pól

SEKCJA_POCZATEK=<{[~=]++}>-

SEKCJA_KONIEC=<//[~=]++>-                        

WARTOSC_LICZBOWA=/={*}>-

WARTOSC_TEKSTOWA=/={*}>-

POLE_NAZWA=<{*}-/=

 

Znaczenia poszczególnych nazw wejść w sekcjach definiujących są  następujące:

KOM_LIN_POCZ - Opisuje sekwencję znaków, które oznaczają początek  komentarza liniowego w pliku danych.        

SEKCJA_POCZATEK - Opisuje sekwencję znaków oznaczającą początek sekcji w pliku danych. Wyrażenie ujęte w nawias klamrowy wydziela z całego opisu nazwę sekcji .

SEKCJA_KONIEC - Opisuje sekwencję znaków, która oznaczać będzie koniec sekcji wejściowej.

POLE_NAZWA - Opisuje nazwę pola danych w pliku wejściowym.  Wyrażenie ujęte w nawiasy klamrowe wydziela samą nazwę pola z sekwencji innych znaków dodatkowych (znaku początku linii, separatorów itd.)

WARTOSC_LICZBOWA - Opisuje wartość liczbową pola. Wyrażenie ujęte w nawiasy klamrowe wydziela samą wartość pola z sekwencji innych znaków dodatkowych (znaku końca linii, separatorów itd.)

WARTOSC_TEKSTOWA - Opisuje wartość tekstową pola. . Wyrażenie ujęte w nawiasy klamrowe wydziela samą wartość pola z sekwencji innych znaków dodatkowych (cudzysłowów, znaku końca linii, separatorów itd.)  

 

Definiowanie formatu w szablonie

Definiowane formatu w szablonie odbywa się w podobny sposób, jak definiowanie formatu w pliku IMPEX.INI, z następującymi różnicami:

Definiując format w szablonie nie określamy nazwy formatu

W szablonie nie tworzymy sekcji, ale wszystkie opisy umieszczane jeden pod drugim

Definiowanie poszczególnych elementów sekcji  musi być w określonym porządku:

definicja początku sekcji

definicja nazwy pola

definicja wartości pola

definicja końca sekcji

 

Dla przykładowego pliku opisanego w poprzednim punkcie definicja w szablonie wyglądałaby następująco

 

#KOM_LIN_POCZ         "<REM> "

#SEKCJA_POCZATEK         "<{[~=]++}>-"

#SEKCJA_KONIEC         "<//[~=]++>- "                        

#WARTOSC_LICZBOWA         "/={*}>-"

#WARTOSC_TEKSTOWA         "/={*}>-"

#POLE_NAZWA        "<{*}-/= "

 

Kiedy definiować własne formaty danych

Zasada jest bardzo prosta, tylko wtedy gdy posiadany plik z danymi nie może być zinterpretowany przy pomocy istniejących formatów. Dużo bezpieczniej jest dopasować się do jednego z gotowych, standardowych formatów niż tworzyć nowy. Standardowe formaty są właściwie niezmienne w czasie (odmiennie niż szablony) i raczej nie będzie potrzeby zarządzania zmianami w formatach. Skorzystamy w ten sposób ze sprawdzonego i przetestowanego wzorca, a także mamy pewność, że następne wersje programu nie wniosą zmian i poprawek uniemożliwiających obsługę nowego formatu (prawdopodobieństwo tego jest niewielkie, ale przy bardzo skomplikowanych konstrukcjach może się zdarzyć).  Do standardowych formatów łatwiej znaleźć opis (chociażby ten podręcznik) oraz osoby które będą potrafiły go obsługiwać i poprawiać ewentualne błędy.

Często jednak nie ma innego wyjścia, gdy na przykład nie można zmodyfikować programu wysyłającego dane, a format przez niego używany jest delikatnie mówiąc „egzotyczny”. Wtedy na pewno lepiej zdefiniować nowy format, niż tworzyć dodatkowe zewnętrzne translatory formatu.

Pamiętajmy jednak, że format danych nie przesądza jeszcze kategorycznie o postaci danych w pliku danych nadawcy!. Dotyczy on bowiem formatowania pojedynczych danych. Ostateczne rozstrzygnięcie w jaki sposób interpretować jakie dane określona jest poprzez szablon, który pobierane dane z pliku przypisuje zmiennym. I tak większość szablonów profili dostarczanych przez aplikacje Symfonii korzysta z formatu AMS.

W przypadkach rozważania nowego importu z nowego programu nadawcy zalecamy użycie formatu danych AMS.