Autor Téma: Přidání listu do sešitu v Excelu  (Přečteno 1081 krát)

Offline PetrB0

  • Plnoletý
  • ***
  • Příspěvků: 169
  • Karma: 1
    • Verze Delphi: Delphi XE2, Delphi 10.2 Tokyo, Delphi 10.41
Přidání listu do sešitu v Excelu
« kdy: 06-06-2024, 02:57:29 »
Pro přístup k Excelu v Delphi 12 používám objekt TExcelApplication.
Nejprve si jej vytvořím App:=TExcelApplication.Create(Nil);
Pak se k němu připojím App.Connect;
Nastavím si úroveň zabezpečení App.AutomationSecurity:=3;
A nechám to běžet na pozadí App.Visible[0]:=False;
Pak si otevřu sešit WB:=App.Workbooks.Open("Soubor",Nul,True,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,0);
A připojím si projektovou část Project:=WB.VBProject;
Mým cílem je přidat si jeden list a do jeho vba modulu si zapsat jenom poznámku 'Moje poznámka
Sešit vložím v pohodě: Sheet:=WB.WorkSheets.Add(Null,WB.Worksheets[WB.Worksheets.Count],1.xlWorkSheet,0);
Nastavím mu nějaké požadované jméno Sheet.Name:='JmenoSesitu'

Ale nedokážu se dostat na jeho Modul.  Přijde mi, že se mi ani nevytvoří. Pokud si zobrazím před přidáním Project.VBComponents.Count a po přidání, jsou tam stejné hodnoty. I obsah je stejný. Přitom by to mělo to přidání registrovat. V tomto seznamu jsou totiž jak listy, tak i moduly, formuláře a třídy.
Když si vyzkouším podobný kód přímo ve vba, tak se počet VBKomponentů zvýší o 1 (což je správně)
Tohle je ten VBA kód
Kód: Delphi [Vybrat]
  1. Private Function Pocet() As Integer
  2. Dim I As Long
  3.  Pocet = ThisWorkbook.VBProject.VBComponents.Count
  4. End Function
  5. Public Sub Test()
  6. Dim WB As Workbook
  7. Dim WS As Worksheet
  8.  
  9. Debug.Print "Pred pridanim=" & Pocet()
  10.  Set WB = ThisWorkbook
  11.  Set WS = WB.Worksheets.Add(Null, WB.Worksheets(WB.Worksheets.Count), 1, xlWorksheet)
  12. Debug.Print "Po pridani=" & Pocet()
  13.  WS.Name = "JmenoSesitu2"
  14.  
  15.  ThisWorkbook.VBProject.VBComponents(ThisWorkbook.VBProject.VBComponents.Count).CodeModule.AddFromString ("'Testovací poznámka")
  16.  
  17. Set WS = Nothing
  18. Set WB = Nothing
  19. End Sub
  20.  

Zkoušel jsem přidat list přímo do VBComponents, ale to vyvolalo Ole chybu. Takže list vytvořím, ale modul k němu nenajdu. Neexistuje nějaký refresh, nebo nemá nějakou chvilku počkat, než se vytvořený modul "propíše" i do seznamu VBComponents?

Máte nějaké nápady co s tím? Mě už došly.

Díky

Pb

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3541
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:Přidání listu do sešitu v Excelu
« Odpověď #1 kdy: 06-06-2024, 07:07:55 »
Predpokladam ze to 1.xlWorkSheet misto 1,xlWorkSheet je jen tady. Sice nevim zda by to proslo, ale pro jistotu.
Embarcadero MVP - Czech republic

Offline PetrB0

  • Plnoletý
  • ***
  • Příspěvků: 169
  • Karma: 1
    • Verze Delphi: Delphi XE2, Delphi 10.2 Tokyo, Delphi 10.41
Re:Přidání listu do sešitu v Excelu
« Odpověď #2 kdy: 10-06-2024, 11:32:29 »
Máš pravdu, byl to jenom překlep.
Další zkoumání mne utvrzují v tom, že rozhraní neaktualizuje seznam VBA objektů po přidání nového listu. Ale třeba dělám něco špatně.

Offline PetrB0

  • Plnoletý
  • ***
  • Příspěvků: 169
  • Karma: 1
    • Verze Delphi: Delphi XE2, Delphi 10.2 Tokyo, Delphi 10.41
Re:Přidání listu do sešitu v Excelu
« Odpověď #3 kdy: 10-06-2024, 16:44:37 »
Zkoušel jsem nový list přidat i pomocí TExcelApplication.VBE.Project.VBComponents.Add(vbext_ct_Document), ale to končí s Ole chybou 800A01B8, což je nějaká obecná OLE chyba (bližší popis jsem nenašel).
Přidávání jiných objektů (formulář, třída, modul) je bez problémů.
Jenom ten dokument zlobí. Jediné řešení je, nejprve přidat TExcelApplication.Workbook.Worksheets.Add... odpojit se od sešitu, zapojit znovu a potom už tam ten VBA modul tohoto nového sešitu mám dostupný.
Myslel jsem, že to je nějakou chybou v mém testovacím sešitu, ale když jsem vzal ten, na kterém jsem si zkoušel fungující VBA kód, tak se přístup z Delphi choval stejně (špatně).

Offline vandrovnik

  • Padawan
  • ******
  • Příspěvků: 1587
  • Karma: 52
    • Verze Delphi: 11.3
Re:Přidání listu do sešitu v Excelu
« Odpověď #4 kdy: 11-06-2024, 09:01:20 »
Já našel v nějakém stařičkém kousku aplikace tohle:

Kód: Delphi [Vybrat]
  1. var fModule: variant;
  2. ...
  3. // novy modul
  4. fModule:=fVBProject.VBComponents.Add(vbext_ct_StdModule);
  5. fModule.Name:='NejakyNazev';
  6. // zapiseme do nej makro na nahravani obrazku
  7. Makro:='Sub NahrajFoto(Formular As String, Soubor As String)'+#13+
  8. ......
  9. 'End Sub';
  10. fModule.CodeModule.AddFromString(Makro);
  11.  

Offline PetrB0

  • Plnoletý
  • ***
  • Příspěvků: 169
  • Karma: 1
    • Verze Delphi: Delphi XE2, Delphi 10.2 Tokyo, Delphi 10.41
Re:Přidání listu do sešitu v Excelu
« Odpověď #5 kdy: 11-06-2024, 09:49:06 »
Ahoj, díky za reakci, ale tohle je něco trošinku jiného. Tahle část mi funguje.
Sešit v Excelu má několik částí:List, Formulář, Modul, Třídu.
K tomu List a Formulář mají ještě vlastní modul.
Sešit si získám třeba otevřením již existujícího souboru
Kód: Delphi [Vybrat]
  1.  pWorkBook:=TExcelApplication.Workbooks.Open(JmenoSouboru,Null,True,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,Null,0);
  2.  
A můžu si z něj zobrazit seznam všech jeho listů
Kód: Delphi [Vybrat]
  1.  For __I:=1 To pWorkBook.Worksheets.Count Do
  2.    Begin
  3.     __V:=pWorkBook.Worksheets.Item[__I];
  4.    End;
  5.  
Zároveň mohu získat seznam VBComponentů (tam jsou všechny VBA Objekty, tedy Modul, Třída, ale i Modul Formuláře a Modul Listu)
Kód: Delphi [Vybrat]
  1.  pProject:=pWorkBook.VBProject;
  2.  For __I:=1 To pProject.VBComponents.Count Do
  3.   Case  Project.VBComponents.Item(__I).type_ Of
  4.    vbext_ct_StdModule         : S:='tvmtModule';  //Klasický vba modul
  5.    vbext_ct_ClassModule       : S:='tvmtClassModule'; //Modul s objektem
  6.    vbext_ct_MSForm             : S:='tvmtForm'; //VBA modul s kódem pro formulář
  7.    vbext_ct_ActiveXDesigner : S:='tvmtOther'; //? tohle přesně nevím, ale nepotřebuji to
  8.    vbext_ct_Document          : S:='tvmtDocument'; //VBA modul s kódem pro List
  9.   Else  S:='tvmtUnknown';
  10.   End;
  11.  
A s VBA kódem v každém komponentu mohu manipulovat přes
Kód: Delphi [Vybrat]
  1.  pProject.VBComponents.Item(I).CodeModule...; //AddFromString,DeleteLines,...
  2.  

Do seznamu VBComponents přidávám pomocí
Kód: Delphi [Vybrat]
  1.  pTyp:=vbext_ct_StdModule nebo vbext_ct_ClassModule nebo vbext_ct_MSForm;
  2.   //   vbext_ct_ActiveXDesigner - to jsem nezkoušel to nepotřebuji
  3.   // vbext_ct_Document          - to jsem zkoušel, ale vyvolá to OLE Error
  4.  pProject.VBComponents.Add(pTyp);
  5.  

Takže kromě vbext_ct_Document mohu ty tři v pohodě přidat a vložit jim VBA kód.
Document musím přidat nejprve jako list
Kód: Delphi [Vybrat]
  1.  Sheet:=pWorkBook.Worksheets.Add(Null,p.WorkBook.Worksheets[pWorkBook.Worksheets.Count],1,xlWorksheet,0); //Tohle přidá sešit na konec
  2.  Sheet.Name:='JménoMéhoListu';
  3.  

A dokud sešit nezavřu, tak v seznamu VBComponents modul pro list nevidím. (Na rozdíl od již ukázaného programu ve VBA, kde to vidím okamžitě). A to ani když mezitím přidávám jiné typy modulů.
Jakmile sešit znovu otevřu, tak si mohu v seznamu Listů najít ten můj a v VBComponents si mohu sáhnout na jeho VBA modul a případně mu nastavit kód.

Řešení ve stylu "Otevři soubor - Přidej list - Zavři soubor - Otevři soubor - Nastav listu VBA" bude fungovat, ale přijde mi to dost kostrbaté, když potřebuji vložit několik listů s VBA.
Nemáte někdo typ, co bych mohl dělat špatně? Možná nějaký blbě použitý parametr, mnou neobjevená funkce pro VBComponents update nebo něco podobného...

Díky
« Poslední změna: 11-06-2024, 09:51:22 od PetrB0 »

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3530
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Přidání listu do sešitu v Excelu
« Odpověď #6 kdy: 11-06-2024, 11:55:04 »
A dokud sešit nezavřu, tak v seznamu VBComponents modul pro list nevidím. (Na rozdíl od již ukázaného programu ve VBA, kde to vidím okamžitě). A to ani když mezitím přidávám jiné typy modulů.
Jakmile sešit znovu otevřu, tak si mohu v seznamu Listů najít ten můj a v VBComponents si mohu sáhnout na jeho VBA modul a případně mu nastavit kód.
Sice uz roky neprogramuju a nemam ani Delphi, ale kdyz se divam do nejakeho kodu, tak vsude volame metodu WorkSheet.Activate, nez s tim sheetem neco delame a to i v pripade, ze je Excel neviditelny. Proc, to si skutecne nepamatuju, ale treba to pomuze.

Offline PetrB0

  • Plnoletý
  • ***
  • Příspěvků: 169
  • Karma: 1
    • Verze Delphi: Delphi XE2, Delphi 10.2 Tokyo, Delphi 10.41
Re:Přidání listu do sešitu v Excelu
« Odpověď #7 kdy: 11-06-2024, 12:48:19 »
Tohle jsem při svých pátráních už také zkoušel, ale nefungovalo to. Tedy nepřineslo to žádnou změnu v seznamu VBComponents.
Pro jistotu jsem to teď znovu vyzkoušel na současném kódu a před přidáním listu i po jeho přidání to stále hlásí stejný počet komponent. Seznam je totožný v obou případech. A když potom aplikaci pustím znovu, mám na konci seznamu nový komponent typu Document (tak jak bych očekával už po přidání listu).
Zkusil jsem i Workbook.RefreshAll. Také nic
« Poslední změna: 11-06-2024, 12:56:10 od PetrB0 »

Offline PetrB0

  • Plnoletý
  • ***
  • Příspěvků: 169
  • Karma: 1
    • Verze Delphi: Delphi XE2, Delphi 10.2 Tokyo, Delphi 10.41
Re:Přidání listu do sešitu v Excelu
« Odpověď #8 kdy: 12-06-2024, 11:36:10 »
Díky za konzultace, na konec jsem to tedy udělal dvoufázové, protože lepší postup jsem nenašel. Otevření sešitu->přidání listu->uložení sešitu do temp adresáře->zavření sešitu->otevření sešitu z temp adresáře->nastavení VBA kódu pro list->uložení sešitu do originální lokace->zavření sešitu.