Fórum pro uživatele kancelářského balíku OpenOffice | LibreOffice
 

#1 24. 4. 2016 16:06:16

LADER
Člen
Registrace: 3. 4. 2013
Příspěvků: 91

Inicializace proměnných

Zdravím,

Mám několik polí definované jako Global
Mám podprogram, kde jim přiřazuji číselné konstanty
Jak to udělat, aby se ten podprogram spustil vždy jako první (pouze jednou, třeba při spuštění programu).
Je to nutné proto, aby funkce, které tyto konstanty používají, počítaly správně a nedělily nulou (chyba když inicializace neproběhla).


A taky bych potřeboval, aby se ty pole při běhu programu nějak nevynulovaly, třeba chybou. Nevím jestli je to možné, tak se ptám pro jistotu. Mám program, který mi počítá pro každou buňku výpočet zvlášť a pokud by nastala třeba chyba, pak bych musel odkliknout třeba 10000x chybu, než by se program ukončil (zatím jsem nepřišel jak to v Calcu udělat jinak, tedy mimo odstřelení ve správci procesů).
Asi by se jednalo o nějakou informaci, že se pole vynulovaly, nebo že se inicializace ztratila. V tom případě by bylo dobré, kdyby inicializace nastala automaticky. Píšu to proto, že se mi to už stalo. Zatím jsem pole inicioval vždy ručně.


Děkuji.

Offline

#2 24. 4. 2016 19:33:52

neutr
Člen
Registrace: 8. 3. 2007
Příspěvků: 2,678

Re: Inicializace proměnných

Proměnné global jsou implicitně prázdné jako Null. Teprve při první inicializaci a přiřazení například nuly se objeví hodnota. Takže na začátku procesů je nutné vždy nejlépe funkcí aktivivat Global proměnnou. Stačí :
Global iVar as long
Function Start
iVar = 0
End Function


     Global by měla vydržet celé sezení, ale pro jistoto můžete na začátku důležitých subroutin nebo funkcí zadat podmínkou IF dotaz jestli je proměnná >= 0. Pak rozhodnout zda znovu aktivace, nebo konec.
     Když by to měla být buňka tak nesmí být prázdná, ale musí tam být alespoň nula. Je sice možné deklarovat jako object, ale Global jsou typicky proměnné typu čísla, nebo string. Takže je lepší načíst obsah buňky do proměnné jako Long, nebo integer, double a podobně.

Editoval neutr (24. 4. 2016 19:41:14)


Pokud je Váš problém vyřešen, označte prosím svůj příspěvek za "VYŘEŠENÝ"
Zlepšíte tak orientaci na fóru při vyhledávání řešení problémů
JAK OZNAČIT TÉMA ZA VYŘEŠENÉ

Offline

#3 24. 4. 2016 21:21:11

LADER
Člen
Registrace: 3. 4. 2013
Příspěvků: 91

Re: Inicializace proměnných

Zdravím,
asi tak to zhruba mám, mimo jiné je na začátku:

Global WA(12) As Double, XA(12) As Double, YA(12) As Double, ZA(12) As Double, MA(12) As Double

pole inicializuji takto:

Sub Main	
	WA = Array(0, 0.035646608082654, 0.016000404490225, 0.015500439437458, 0.010315267586293, _
		0.010105137896732, 0.010315267586293, 0.0041883679973837, 0.0032504786329787, _
		0.0076109906967816, 0.0060458168932457, 0.0074959810297708, 0.012420246492211)

	XA = Array(0, 0.0, 0.016000404490225, 0.0, 0.020630535172586, 0.010105137896732, _
			0.020630535172586, 0.016753471989535, 0.019502871797872, 0.022832972090344, _
			0.024183267572982, 0.014991962059541, 0.012420246492211)
	
	YA = Array(0, 0.0 ,0.016000404490225, 0.015500439437458, 0.041261070345173, _
			0.020210275793465, 0.041261070345173, 0.025130207984302, 0.026003829063829, _
			0.022832972090344, 0.018137450679737, 0.022487943089312, 0.012420246492211) 			
	
	ZA = Array(0, 0.0, 0.016000404490225, 0.0, 0.020630535172586, 0.010105137896732, _
			0.020630535172586, 0.016753471989535, 0.019502871797872, 0.022832972090344, _
			0.012091633786491, 0.014991962059541, 0.0)

	MA = Array(0, 28.05316, 62.49842, 64.5143, 96.94368, 98.95956, 96.94368, 119.37824, _
			153.8235, 131.38894, 165.40362, 133.40482, 80.5137)	
	
End Sub

a v důležitých funkcích mám na začátku toto:

If MA(1)<>28.05316 Then Call Main 

takže lepší způsob asi není...

a teď jak to udělat, aby se mi subrutina Main spustila automaticky při nahrání programu? Jde to?

Offline

#4 24. 4. 2016 22:41:35

lp.
Člen
Registrace: 24. 9. 2009
Příspěvků: 790

Re: Inicializace proměnných

Zkuste Nástroje, Přizpůsobit, Události a zvolte vhodnou událost pro spuštění makra. Např. Otevřít dokument.

Ten test a inicializaci v procedurách bych ale zatím nemazal.

Co se týká odklikávání chyb, v basicu je na to příkaz

On Error ...

V tomto případě

On Error GoTo ObsluhaChyby

   <Program>

   Exit sub
ObsluhaChyby:
   On Error GoTo 0
   <Nějaká akce>
   <Náprava nebo ukončení procedury>

Pokud je náprava, tak je rutina zpravidla ukončeno příkazem Resume
Pokud ukončujeme, je vhodné uklidit a Exit Sub.

Editoval lp. (24. 4. 2016 22:42:43)

Offline

#5 25. 4. 2016 06:39:27

neutr
Člen
Registrace: 8. 3. 2007
Příspěvků: 2,678

Re: Inicializace proměnných

Ještě mne napadla jedna věc mimo toho, že jsem nějak přeskočil ten dotaz na automatické spuštění. Při tom bych na to asi nezapoměl. Jde o to, že Incializace pole "ručně" by v případě Vašich ověřovacích dotazů If neměla být potřeba. Správně provedený ověřovací dotaz by měl udělat v případě potřeby inicializaci a nic by se jako chyba neprojevilo.
     Problém by mohl být pokud máte například Main v jiné knihovně. Například v knihovně "Moje Standard" a vlastní kód například v sešitě. Jde o to, že těch maker "Main" můžete mít v knihovnách více - tedy v různých modulech.
     Pak by docházelo k volání nesprávného makra Main a proměnné by nefungovaly. Potom dává smysl i to, že je aktivujete ručně - protože bezpečnostní dotaz je neumí spustit.



     Pomůže volání makra i s kvalifikovanou cestou ke knihovně. Zase na druhou stranu je pak jedno jestli to spouštíte bezpečnostním dotazem, nebo událostí.


Pokud je Váš problém vyřešen, označte prosím svůj příspěvek za "VYŘEŠENÝ"
Zlepšíte tak orientaci na fóru při vyhledávání řešení problémů
JAK OZNAČIT TÉMA ZA VYŘEŠENÉ

Offline

#6 25. 4. 2016 15:03:41

LADER
Člen
Registrace: 3. 4. 2013
Příspěvků: 91

Re: Inicializace proměnných

lp. napsal(a)

Zkuste Nástroje, Přizpůsobit, Události a zvolte vhodnou událost pro spuštění makra. Např. Otevřít dokument.

Přidal jsem tam podle tohoto návodu a abych měl jistotu, že to proběhlo, tak jsem ještě navíc přidal hlášení MsgBox o proběhlé inicializaci.

Příkaz on error znám, mě se jedná spíše o neočekávanou/nepředpokládanou chybu. Snažím se psát program tak, aby chyba nevznikla.
Pokud nastane (což se normálně vůbec nestává, jenom třeba při odlaďování, když při úpravě se třeba upíšu o písmenko), pak vzhledem k tomu, že pracuji s velkým množstvím dat, výpočtů je mnoho a nejenom že  výsledky se počítají iteračně, ale i na sebe navazují, pak všechny následující výpočty už pracují s nesmyslnými daty a je lepší všechny výpočty ukončit. Myslel jsem nějaké centrální tlačítko "STOP", jako dříve co bývalo na klávesnici "Pause/Break", které dnes již nefunguje.
Samozřejmě lze do každé funkce zabudovat on error goto, ale stejně všechny funkce jsou volány dál, i když třeba pak nic nedělají. Kdysi jsem s on error experimentoval a vzhledem k tomu, že mi značně zpomalovaly program, tak jsem od toho upustil (a odladěný program chyby nedělá). Nevím jak teď, třeba je situace jiná.

Offline

#7 25. 4. 2016 15:57:17

neutr
Člen
Registrace: 8. 3. 2007
Příspěvků: 2,678

Re: Inicializace proměnných

Jen pro ladění v tom smyslu by mělo On ERROR GoTo odkazovat na makro které bude obsahovat Stop + například hlášení co to způsobilo, nebo na které funkci (sub) to vzniklo.
     Princip může být v tom, že název makra můžeme hromadně přejmenovat (a tím přepnout na jiné makro které bude testovat něco jiného, nebo chybu přeskočí), nebo celý řádek smazat a tím tento element po odladění zcela odstranit.
     Vlastní sekvenci umožňující okamžitý "stop" sestrojit nelze. Nejlepší je právě podmínku přednastavit na začátek každého procesu. Například stačí Deklarovat proměnnou Global as Boolean a postavit podmínku například na false.


     Takže makro se stopem lze postavit například na událost OnClick ale musí být součástí testů před, nebo po skončení operací. Určitě byste si poradil s inicializací testovacího provozu například pomocí dvou proměnných Global Boolean. První proměnná by zapínala čtení druhé proměnné.
     Takže pak máte možnost plynule přepínat mezi ostrým provozem a provozem ladění (mimo práci v IDE). Ale úplně bez předřazených sekvencí "testů" to nepůjde. Mám zkušenost že makra vypínám pomocí tlačítka z rozhraní IDE (červený puntík) - ale pokud to zkusíte uvidíte že se to ne vždy zadaří. U nekterých maker musím strefovat správné místo - jinak tlačítko nefunguje.
     Domnívám se, že je to chyba LO (AOO). nekdy do verze LO 3.2.1 fungovalo paralelní stisknutí tlačítka napojeného na makro se "STOP". Zjistil jsem že od té doby to funguje jenom někdy - bohu žel nevím proč. Proto jsem začel předřazovat test na podmínku provozu.

Editoval neutr (25. 4. 2016 15:58:32)


Pokud je Váš problém vyřešen, označte prosím svůj příspěvek za "VYŘEŠENÝ"
Zlepšíte tak orientaci na fóru při vyhledávání řešení problémů
JAK OZNAČIT TÉMA ZA VYŘEŠENÉ

Offline

#8 25. 4. 2016 17:48:00

lp.
Člen
Registrace: 24. 9. 2009
Příspěvků: 790

Re: Inicializace proměnných

LADER napsal(a)

Myslel jsem nějaké centrální tlačítko "STOP", jako dříve co bývalo na klávesnici "Pause/Break", které dnes již nefunguje.

Zkuste ctrl-shift-Q .

LADER napsal(a)

Samozřejmě lze do každé funkce zabudovat on error goto, ale stejně všechny funkce jsou volány dál, i když třeba pak nic nedělají. Kdysi jsem s on error experimentoval a vzhledem k tomu, že mi značně zpomalovaly program, tak jsem od toho upustil (a odladěný program chyby nedělá). Nevím jak teď, třeba je situace jiná.

Ano, lze. Ale pokud je to zabudované někde v hlavní proceduře, tak to platí i pro vnořené.

Sub Main
	on error goto Chyba
	proceduraX
	exit sub
Chyba:
	print "Chyba : " & error$
End Sub

sub proceduraX
	proceduraY
end sub


sub proceduraY
	b = 0
	a = 45/b
end sub

Offline

#9 25. 4. 2016 20:19:38

LADER
Člen
Registrace: 3. 4. 2013
Příspěvků: 91

Re: Inicializace proměnných

Díky za ctrl-shift-Q to zkusím, ale obávám se, že to ukončí pouze aktuálně běžící makro. Ty paralelně běžící se budou muset zastavovat jednotlivě (nejsou totiž volány z centrální procedury, každá buňka je počítaná jednotlivě zvlášť svou funkcí, byť s jinými vstupními hodnotami).


Když se dostanu do tohoto stavu, tak se nedostanu vůbec do Calcu, ani do editoru maker i když je mám navrchu na ploše, prostě hlášení chyby je výše a tím má vyšší prioritu, abych se dostal do Calcu, nebo do editoru, musím odklepnout chybové hlášení. V momentě odklepnutí je tam ale další, takže mám dvě možnosti, buď trpělivě odklepávat (což není časově realizovatelné), nebo odstřelit Calc ve správci procesů. Pak ale nesmím spustit obnovu dokumentů, protože bych přišel o celou práci. Musím si načíst poslední uloženou zálohu (a tu případně upravit).


Asi budu muset uvažovat o globální proměnné, která bude testovaná na začátku každé funkce - tohle mě fakt nenapadlo - i když je to logické. Nevýhoda je, že budu muset ještě vpravit on error do každé funkce. Nešlo by to nějak mimo tyto funkce udělat? Jako globální nadřazené on error?


Jinak by bylo dobré, kdyby hlášení chyby umožňovalo si vybrat, mezi pokračováním a úplným odstavením - a tím přejít do režimu ladění, kde by se chyba dala zeditovat.

Offline

#10 26. 4. 2016 04:57:30

neutr
Člen
Registrace: 8. 3. 2007
Příspěvků: 2,678

Re: Inicializace proměnných

Teoreticky by příkaz STOP měl být nadřazen všem procesům a všechny procesy zastavit. "Exit Sub" zastavuje jenom jedinou proceduru (podobně funkci "Exit function") takže pak mohou ostatní pokračovat. Jde samozřejmě o umístění On Error v hierarchii kódu.
     Takže teoreticky by STOP z podřízeného makra měl zastavit nejen sobě nadřazené makro, ale úplně vše. Bohu žel je to asi stejný problém jako s tím červeným puntíkem.


      Také je někdy dobré se zamyslet jak koncipovat strukturu :
Když uděláme hlavní makro ze kterého voláme řadu jiných maker stane se to co popisujete.


Sub Hlavni
  Call Pomocne1
  Call Pomocne2
  ...........
  Call Pomocne3 = chyba
  'Když vznikne chyba makro Pomocne3 skončí ale běh se přenese do dalšího
  Call Pomocne4
End Sub


Je to podobně jako když dáte makro nebo funkci do cyklu. Cyklus jede stále a volá makro s chybou.
For i = 0 To XY
Call NejakeMakro
Next i
     Tam se samozřejmě musí dát Exit For a za měj by mělo přijít "Exit Sub, ale k tomu nedojde protože skočíme za cyklus. Pomůže jen STOP, ale tím si také už nejsem úplně jistý.


      Když ale navážete makra tvrdě do série (makro A na konci volá makro B a to zase makro C....) tak bude fungovat i On Error s "Exit Sub" na každém makru. Samozřejmě makra pak končí na Exit Sub protože mezi Exit Sub a End Sub se vkládá návěští chyby.
      Z hlediska úprav to vychází nastejno - tedy zda připsat na začátky test na proměnnou boolean, nebo na konec. Ovšem pokud chcete vytvořit verzi která se dá přepnout na testovací, tak musíte dělat úpravy na konci.


      Nejlepším řešením pro takové makro je sada příkazů Go Sub za návěštím pro chybu.
příklad kódu :

Sub XYZ
ON ERROR GOTO Navestichyby
  ......
  ......
Exit Sub
Navestichyby:
Dim iVar as integer
---------------------jednoduchá verze
iVar = MsgBox(..........,4,.)
  IF iVar = 7 Then
        Stop
  End IF
--------------------alternativa kam se dá přidat ElseIF
  IF .......'podmínka pro první případ zastavení s dotazem (stačí 1 nebo žádná proměnná Global)
      Stop
  ElseIF ....'složitější řešení - ladíme s dotazem
    Go Sub SubA........Test proměnné A
    Go Sub SubB........Test proměnné B
  Else ......'jednodušší řešení - ladíme bez dotazu
    Go Sub SubA........Test proměnné A
    Go Sub SubB........Test proměnné B
  End If
--------------------
SubA:
  kód ......
Return
SubB:
  kód......
Return
'.....Případně skok na testy jiných parametrů př:
  Call Testujeme(A,B)
' nebo jen hláška
End sub


      Když tam ještě vložíme další ElseIF tak můžeme plynule nastavit přechody (běžný provoz) - (testovací provoz) - (běžný provoz). K tomu proložit dotazy zda skončit nebo pokračovat. V Calcu je výhoda možnosti zapisovat průběh činnosti do sešitu a pak si to OffLine projít. Samozřejmě je to trošku náročnější ale Vám by se to asi vyplatilo.

Editoval neutr (26. 4. 2016 05:38:50)


Pokud je Váš problém vyřešen, označte prosím svůj příspěvek za "VYŘEŠENÝ"
Zlepšíte tak orientaci na fóru při vyhledávání řešení problémů
JAK OZNAČIT TÉMA ZA VYŘEŠENÉ

Offline

Zápatí