Tydzień temu pisałem o drukowaniu dokumentów w Pythonie stosując metody biblioteki Qt4. Wszystko w kontekście tworzenia Kart Ewidencji Zabytków Archeologicznych (KEZA), które wypełnia się przede wszystkim na okoliczność prowadzenia badań w ramach projektu Archeologicznego Zdjęcia Polski.
Przypatrując się wzorcowej karcie KEZA można zauważyć, że faktycznie jest to bardzo rozbudowana tabela ze scalonymi komórkami. Eksperyment przeprowadzony przy pomocy Excela wykazał, że podobny efekt można osiągnąć stosując tabelę z 60 kolumnami i 35 wierszami równej wysokości, która wypełnia arkusz A4.
Wstawianie tabeli
To okazało się szczęśliwym zrządzeniem losu, ponieważ dzięki temu i wykorzystaniu klas QTextDocument i QTextCursor nie musiałem implementować własnoręcznie funkcji rysującej tabelę. Zamiast tego mogłem wykorzystać metodę insertTable(wiersze, kolumny, format) klasy QTextCursor. Znaczenie dwóch pierwszych parametrów powinno być oczywiste. W pierwszym podaje się liczbę wierszy, w drugim liczbę kolumn. W przypadku tworzenia karty KEZA istotny jest trzeci, za pomocą którego określa się właściwości tabeli, takie jak obramowanie (border-style), odległość między obramowaniem a zawartością komórki (cellpadding). Te i inne parametry określa się w obiekcie klasy QTextTableFormat, podawanym jako trzeci argument metody insertTable. Po wykonaniu zwraca ona obiekt klasy QTextTable.
Przykład
Kod programu Pythona rozpoczynając od inicjalizacji klasy QTextDocument do wstawienia nowej tabeli mógłby wyglądać następująco:
doc = QTextDocument()
cur = QTextCursor(doc)
fmt = QTextTableFormat()
fmt.setCellPadding(1)
fmt.setBorderStyle(QTextFrameFormat.BorderStyle_Solid)
keza = cur.insertTable(35,60,fmt)
W sześciu liniach została utworzona duża tabela, zawierająca ponad 2100 komórek. Teraz kwestią pozostaje ich scalenia w taki sposób, żeby po wszystkim przypominała wzór karty KEZA. Do połączenia grupy komórek można zastosować metodę mergeCells(y, x, wysokosc, szerokosc) klasy QTextTable, gdzie argumenty y oraz x oznaczają lokalizację pierwszej komórki w grupie łączonych (licząc od lewego górnego narożnika), a wysokość i szerokość to odpowiednio liczba komórek w pionie i w poziomie, które mają być scalone. Chcąc połączyć 6 komórek w górnym lewym rogu tabeli o wymiarach 3 x 2 trzeba wykonać polecenie keza.mergeCells(0,0,2,3). W przypadku generowania karty KEZA takich operacji jest zbyt dużo, aby każdą z osobna zapisywać jako wywołanie powyższej funkcji, dlatego zamiast tego stosuję prosty schemat w postaci pliku CSV, który zawiera definicję każdej docelowej komórki.
Formatowanie komórek
Na koniec pozostaje problem, jak odwołać się do wybranej komórki i wstawić do niej zawartość. Za pomocą metody cellAt(y,x) klasy QTextTable uzyskuje się referencję do komórki o podanych współrzędnych, którą reprezentuje klasa QTextTableCell. Metodą firstCursorPosition() można ustawić w niej kursor (dla przypomnienia reprezentuje go klasa QTextCursor) a następnie użyć go do wstawienia np. tekstu przy pomocy insertText(tekst). To nie wszystko każdą z komórek można formatować. Do tego potrzeba uzyskać informacje o jej bieżącym wyglądzie przy pomocy metody format() klasy QTextTableCell, a następnie stosując odpowiednie metody zmienić formatowanie. Na przykład metoda setBackground(Qt.yellow) zmieni tło komórki z białego na żółty. Na koniec należy to formatowanie jawnie zaplikować do komórki wywołując metodę setFormat. Bez tego zmiana tła będzie bezskuteczna.
Kontynuacja przykładu
keza.mergeCells(0,0,2,3)
grupa = keza.cellAt(0,0) # pobiera scaloną przed chwilą grupę komórek
gf = grupa.format() # formatowanie komórek
gf.setFont(QFont('Times',8,QFont.DemiBold))
grupa.setFormat(gf) # jawne wprowadzenie formatowania
grupa.firstCursorPosition().insertText('QAZP2') # zawartość komórki
drukarka = QPrinter()
doc.print_(drukarka) # wydrukowanie dokumentu na urządzeniu.