DevOpsDay19


Častým požadavkem na programátory ve VFP je komunikace s Excelem. Uživatelé Excel znají a umí v něm data dále zpracovat, takže je mnohdy výhodné přenést data z VFP do Excelu, předzpracovat je a pak už nechat vše na uživateli. Pojďme si tedy ukázat jednoduchý příklad komunikace s Excelem.

Igor VítIgor Vít
SoftwareSoftware
25.03.2009 13:40:0025.03.2009 13:40:00

Igor Vít

Microsoft Most Valuable Professional

DAQUAS
+420 222 512 201
+420 603 442 434
daquas@daquas.cz
Anny Letenské 7, Praha 2

Volám kancelář!

Častým požadavkem na programátory ve VFP je komunikace s Excelem. Uživatelé Excel znají a umí v něm data dále zpracovat, takže je mnohdy výhodné přenést data z VFP do Excelu, předzpracovat je a pak už nechat vše na uživateli. Pojďme si tedy ukázat jednoduchý příklad komunikace s Excelem.

Co chceme dosáhnout

Naším cílem bude přenést data z VFP do Excelu a zobrazit uživateli souhrn dat – pro lepší vysvětlení si ukážeme screenshot (z Office 2007, ale funguje to samozřejmě i ve starších verzích):

screenshot

Spustíme Excel

Nejdříve musíme samozřejmě nastartovat Excel. Dovolím si jen poznamenat, že co verze Excelu, to jiné chování, pokud jde o využití již běžících instancí Excelu, takže my zde použijeme pouze ten nejjednodušší způsob (a navíc v celém programu neprovádím žádné kontroly na chyby apod. – to už si budete muset doplnit).

LOCAL oExcel AS Excel.Application
oExcel = CREATEOBJECT("Excel.Application")
* chceme pouze 1 sheet v novém worksheetu



oExcel.SheetsInNewWorkbook = 1

oExcel.Workbooks.Add() && vytváříme nový sheet

Zde stojí za zmínku pouze příkaz LOCAL, který nám zajistí fungování Intellisense v programu.

Nastavíme vlastnosti Excelu

Určitě budeme chtít, aby byl Excel maximalizovaný přes celou obrazovku. My ale dosáhneme ještě navíc toho, že uživatel Excel uvidí (.Visible = .T.), ale nebude moci nic měnit (.Interactive = .F.)! To je důležité proto, že by jinak mohl v průběhu výpočtu mazat data atd. Navíc ještě zakážeme zobrazení všech dialogů (.DisplayAlerts = .F.), takže by se Excel ani neptal, jestli skutečně chceme skončit bez uložení souboru,… Tohle jsou skutečně důležitá a užitečná nastavení.

oExcel.WindowState = -4137  && xlMaximized
oExcel.Interactive = .F.
oExcel.DisplayAlerts = .F.
oExcel.Visible = .T.

Vytvoříme testovací data

Vzhledem k tomu, že potřebuji trochu složitější data, použiji SELECT na data z Tastrade:

OPEN DATABASE _samples+"tastrade\data\tastrade"
SELECT ;
 Customer.company_name AS Firma, ;
 Orders.order_id AS Objednávka, ;
 SUM(oli.unit_price*oli.quantity) AS Částka,;
 AVG(oli.unit_price) AS PrůměrnáCena ;
FROM Customer ;
INNER JOIN Orders ON Customer.customer_id = Orders.customer_id ;
INNER JOIN Order_line_items AS oli ON Orders.order_id = oli.order_id;
GROUP BY Customer.company_name, Orders.order_id ;
ORDER BY Customer.company_name, Orders.order_id ;
INTO CURSOR q

Přeneseme data do clipboardu

V mnoha případech nejrychlejší a nejúčinnější způsob přenosu dat je pomocí clipboardu. Uložíme proto data z cursoru do clipboardu pomocí _VFP.DataToClip – to je skutečně rychlé a jednoduché:

_VFP.DATATOCLIP(,,3)

Teď zavřeme databázi. Navíc ještě potřebujeme odstranit mezery, abychom zbytečně do Excelu nepřenášeli 50 znaků, kde bude 40 mezer.

CLOSE DATABASES
DO WHILE SPACE(5)$_CLIPTEXT
 _CLIPTEXT = STRTRAN(_CLIPTEXT, SPACE(5), "")
ENDDO
DO WHILE " "+CHR(9)$_CLIPTEXT
 _CLIPTEXT = STRTRAN(_CLIPTEXT, " "+CHR(9), CHR(9))
ENDDO

Data z clipboardu do Excelu

Jelikož máme data v clipboardu, přeneseme je do Excelu velmi jednoduše:

oExcel.ActiveSheet.Range("A1").Select()
oExcel.Selection.PasteSpecial

Rychlé zformátování

Na vzhledu záleží :-), takže provedeme rychlé zformátování:

oExcel.Selection.AutoFormat(17, .t.,.t.,.t.,.t.,.t.,.f.)
oExcel.Cells.EntireColumn.AutoFit

Vytvoření souhrnů dat

Nyní to bude trochu složitější, ale to je vlastně to, co Vám chci hlavně ukázat :-). Jde o použití funkce COMARRAY, pomocí které specifikujeme, jak budeme nějakou referenci (v našem případě referenci na oblast zkopírovaných dat) předávat COM serveru. Bez tohoto nastavení se Vám nepodaří něco takového vůbec dosáhnout!

* vybereme, co budeme sčítat
oSelected = oExcel.Selection
 
* Ujistíme se, že pole (array) se předává referencí a s indexováním od 1
COMARRAY(oSelected, 11)
 
* Chceme sčítat sloupce 3 a 4
LOCAL ARRAY laArray(2)
laArray(1) = 3
laArray(2) = 4
#DEFINE xlSum          -4157
#DEFINE xlSummaryBelow     1
oSelected.Subtotal(1, xlSum, @laArray, .T., .F., xlSummaryBelow)
oSelected = NULL

Hotovo

Data jsou pro uživatele připravena a uživatel může začít pracovat. Je mnoho způsobů, jak ukončit práci, my zvolíme ne úplně ideální :-) – ukončíme Excel a ten se tedy automaticky uživatele zeptá, kam chce tento worksheet uložit. Samozřejmě musíme nejprve povolit komunikaci s uživatelem:

oExcel.Interactive = .T.
oExcel.DisplayAlerts = .T.
oExcel.Quit()
oExcel = NULL

Zde si můžete stáhnout kód k tomuto článku.

A to je vše. Mějte se krásně.

Milan Kosina