Nell’accingermi a raccontare le mie esperienze con il DDE mi sento in dovere prima di tutto di ringraziare coloro che, in egual misura, con il loro costante aiuto, suggerimenti, spiegazioni e sopratutto con la loro infinita pazienza mi hanno permesso di risolvere il mio problema.
Mi riferisco agli utenti:
Antony47 del forum
pc-facile.com
Scossa del forum
archi.forumup.it
Icecube del forum
finanzaonline.com
Paolo1956 del forum
finanzaonline.com
Alcune considerazioni sul DDE :
1° so perfettamente che la tecnica del DDE è antiquata ma questa ho e questa devo usare
2° non è adatto a gestire grandi moli di dati specialmente in relazione al real time (millesimo di secondi)
3° non vuole assolutamente sostituirsi agli strumenti professionali delle banche, Sim ecc. ecc
4° pur tuttavia fa onestamente il proprio lavoro.
Come funziona il mio DDE :
1° sul sito della banca viene attivata la funziona DDE
2° sul PC utente viene lanciato un programma generalmente fornito dalla stessa banca
3° i due programmi si sincronizzano e nella barra del PC utente l’icona diventa verde
4° si lancia la cartella Excel utente e nelle celle dove ci sono le formule DDE arrivano i dati.
Cosa sono , come sono fatte e dove vanno messe le formule DDE :
Ogni fornitore di dati usa propri parametri per indicare nelle formule quali dati l’utente vuole ma sostanzialmente alla fine sono moto simili fra di loro.
Nel mio caso la formula è
dove
FDF|Q! è l’identificativo delle mia banca
'FNC.MI; è il codice del titolo usato dalla banca in questo caso sigla di Finmeccanica
2' indica il dato che si vuole in questo caso l’ultimo prezzo
Quindi per ottenere tale dato dovremmo immettere in una cella Excel la formula :
= FDF|Q!'FNC.MI;2'
Per ottenere il Last Time dello stesso titolo la formula da mettere in un’altra cella sarà :
=FDF|Q!'FNC.MI;14'
e così per altri dati quali open, volume, percent change, bid, ask ecc.ecc
Le formule possono essere messe in qualsiasi cella di qualunque foglio della cartella.
Va tenuto presente comunque che per ogni formula e quindi per ogni titolo viene aperto un
canale DDE il che significa che se ci sono 8 formule in un foglio, 12 in un altro e 7 in un terzo anche se ridondanti fra di loro ed i titoli sono 10 si avranno un totale di
8 * 12* 7 * 10 = 6720 canali
quindi è giocoforza diminuire drasticamente il loro numero.
Nel mio caso, cartella con 6 fogli, quello per me primario era formato da 11 righe ,una per titolo che voglio ottenere, così composta :
sigla titolo, denominazione, prezzo, last time ed altre colonne e quindi 4 formule per riga.
Inoltre in ordine diverso le stesse formule per gli stessi dati esistevano anche negli altri 5 fogli.
Allora cosa ho fatto:
1° sostituite le formule della sigla titolo e denominazione con delle costanti
in quanto so perfettamente che se chiedo il prezzo della sigla FNC.MI si tratta del titolo con denominazione FINMECCANICA.
2° le formule rimaste ridondanti degli altri fogli le ho sostituite con la funzione
Excel ” =nomefoglio!J8” dove J8 è la coordinata della cella dove è stata immessa la formula appropriata.
Come senz’altro, ai più noto, per visualizzare il codice VBA cliccando il tasto destro del mouse sul nome delle linguette dei fogli si apre una finestra che fra le altre ha anche la scelta “VISUALIZZA CODICE” evidenziando il quale e cliccando con il destro si ottiene il codice VBA.
A questo punto scegliendo in alto “VISUALIZZA” si apre una finestra e scegliendo la riga riportante “GESTIONE PROGETTI” si ha sulla destra una sezione così composta :
VbaProject (nome della mia cartella)
Microsoft Excel Oggetti
Foglio1 (Formule) fra parentesi il nome che ho dato al foglio1
Foglio2 (Ordinario) fra parentesi il nome che ho dato al foglio2
……
……
fino al Foglio6 (Movimenti azioni) fra parentesi il nome che ho dato al foglio6
ThisWorkbook
Form
Userform1
Userform2
Moduli
Moduli1
Moduli2
..... e così riga per riga fino alla fine
Moduli di classe
Classe1
Classe2
Classe3
Alcune considerazioni su questa struttura :
1° Nei fogli, si consiglia da più parte, di mettere solo gli eventi Excel quali:
Worksheet_SelectionChange(ByVal Target As Range)
Worksheet_Calculate
<code></code><code>
........ e cosi via dicendo</code>
<code> </code>
2° Nei moduli, si consiglia da più parti, vanno messe le routine public.
3° Alcuni chiamano i moduli anche con il nome Standard quindi quando vi suggeriscono di mettere delle istruzioni fatevi spiegare esattamente dove e perché.
4° Tenete presente che per visualizzare il codice di un Foglio o ThisWorkbook o di un modulo o form o Classe dovete evidenziare cioè che volete quindi tasto destro e poi visualizza codice.
E finalmente passiamo ad commentare tutti i passi fatti.
1° ho inserito in ThisWorkbook il codice
Code:
Private Sub Workbook_Open()
Call LinkList
End Sub
All’apertura della cartella queste istruzioni sono eseguite per prime e passano il controllo alla routine, di nome a piacere, LinkList
2° ho inserito nel Modulo1 la routine pubblica Linklist
Code:
Public Sub LinkList()
ActiveWorkbook.SetLinkOnData "FDF|Q!'ASR.MI;2'", "Macro1"
ActiveWorkbook.SetLinkOnData "FDF|Q!'C40.PAR;2'", "Macro2"
ActiveWorkbook.SetLinkOnData "FDF|Q!'BP.MI;2'", "Macro3"
ActiveWorkbook.SetLinkOnData "FDF|Q!'BNG.MI;2'", "Macro4"
ActiveWorkbook.SetLinkOnData "FDF|Q!'CED.MI;2'", "Macro5"
ActiveWorkbook.SetLinkOnData "FDF|Q!'ENEL.MI;2'", "Macro6"
ActiveWorkbook.SetLinkOnData "FDF|Q!'EGPW_C.MI;2'", "Macro7"
ActiveWorkbook.SetLinkOnData "FDF|Q!'ENG.MI;2'", "Macro8"
ActiveWorkbook.SetLinkOnData "FDF|Q!'FNC.MI;2'", "Macro9"
ActiveWorkbook.SetLinkOnData "FDF|Q!'IRE.MI;2'", "Macro10"
ActiveWorkbook.SetLinkOnData "FDF|Q!'UCG.MI;2'", "Macro11"
End Sub
Perché ho scartato l’esempio di seguito esposto fornito dai più Microsoft compresa?
Code:
Public Sub LinkList()
Dim Links As Variant
' Obtain an array for the links to Excel workbooks
' in the active workbook.
Links = ActiveWorkbook.LinkSources(xlOLELinks)
' If the Links array is not empty, then open each
' linked workbook. If the array is empty, then
' display an error message.
If Not IsEmpty(Links) Then
For i = 1 To UBound(Links)
ActiveWorkbook.SetLinkOnData Links(i), "LinkChange"
Next i
Else
MsgBox "This workbook does not contain any links " & _
"to other workbooks"
End If
End Sub
A – Il sistema delle 11 macro mi permette di avere immediatamente l’indicazione della riga in cui il prezzo è variato.
Notare che se anche manca il DDE time o di altri dati gli stessi arriveranno nelle celle dei fogli in cui sono immesse le relative formule.
In definitiva non è tanto importante avere tanti SetLinkOnData ma solo uno per titolo; la scelta dipende dall’architettura del vostro progetto.
B - Il sistema dell’unico SetLinkOnData ha lo svantaggio che poi costringe a programmare dei controlli ( loop od on timer) per individuare quale cella è variata anche in considerazione del fatto che gli eventi :
<!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:HyphenationZone>14</w:HyphenationZone> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Tabella normale"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman";} </style> <![endif]--> Worksheet_SelectionChange(ByVal Target As Range)
Worksheet_Calculate
non scattano per effetto del variare di una cella DDE (parola di Microsoft)
<code></code>
<code></code>3° ho inserito nel Modulo2 le tredici macroN
Code:
Public Sub Macro1()
nriga = 8
Call LinkChange(nriga)
End Sub
Public Sub Macro2()
nriga = 9
Call LinkChange(nriga)
End Sub
Public Sub Macro3()
nriga = 10
Call LinkChange(nriga)
End Sub
Public Sub Macro4()
nriga = 11
Call LinkChange(nriga)
End Sub
Public Sub Macro5()
nriga = 12
Call LinkChange(nriga)
End Sub
Public Sub Macro6()
nriga = 13
Call LinkChange(nriga)
End Sub
Public Sub Macro7()
nriga = 14
Call LinkChange(nriga)
End Sub
Public Sub Macro8()
nriga = 15
Call LinkChange(nriga)
End Sub
Public Sub Macro9()
nriga = 16
Call LinkChange(nriga)
End Sub
Public Sub Macro10()
nriga = 17
Call LinkChange(nriga)
End Sub
Public Sub Macro11()
nriga = 18
Call LinkChange(nriga)
End Sub
Qui si capisce perché la scelta è caduta sul metodo A in quanto ogni macro imposta la riga del
proprio titolo e chiama la routine LinkChange (anche essa nome a piacere)
4° ho inserito la routine LinkChange nel Modulo2 ma potrebbe andare in qualunque altro modulo :
Code:
Public Sub LinkChange(priga)
If IsError(Range("J" & priga).Value) Then GoTo finejob
If IsError(Range("N" & priga).Value) Then GoTo finejob
If Range("J" & priga) > Range("Q" & priga).Value Then
Range("J" & priga).Interior.ColorIndex = 4
lSuono = 10
Else
If Range("J" & priga) < Range("Q" & priga).Value Then
Range("J" & priga).Interior.ColorIndex = 3
lSuono = 11
End If
End If
Range("J" & priga).Select
Range("Q" & priga).Value = Range("J" & priga).Value
Range("R" & priga).Value = Range("N" & priga).Value
GeneraSuono lSuono
finejob:
End Sub
Considerazioni e spiegazioni:
1° Quando si passa una variabile ad una routine non è che si passa la variabile ma il suo contenuto quindi la Call LinkChange(nriga) passa il valore della sua variabile nriga.
La Public Sub LinkChange(priga) prende quel valore e lo mette nella sua variabile priga.
2° (Range("J" & priga).Value) significa considerare il valore della cella Jx dove x sarà il numero della riga passato da una delle 11 macro cioè da J8 fino a J18.
3° IsError è necessaria perché se una cella DDE non viene calcolata, se non arriva il relativo dato ad esempio il titolo entra in contrattazione ad orario successivo ad altri titoli oppure è sospeso per l’intera giornata, all’apertura della cartella Excel calcola la formula come errore ma pur tenendone conto lascia la visualizzazione precedente.
Di conseguenza qualsiasi istruzione con quella cella dà l’errore 13 Tipo non corrispondente.
Con tale istruzione quindi si bypassano le celle che darebbero l’errore perché la colonna J contiene i prezzi mentre la colonna N contiene il last time dell’ultimo prezzo.
Infatti da J8 a J18 ci sono le formule DDE per chiedere il prezzo mentre da N8 a N18 ci sono le formule DDE per ottenere il last time.
4° Per capire se l’ultimo prezzo arrivato è maggiore o minore al precedente occorre avere delle aree che i più chiamano “ombra” io direi di salvataggio o d’appoggio.
Tale aree possono stare anche su altri fogli e possono essere dichiarati invisibile ecc. ecc.
Nel mio caso sono state individuate nello stesso foglio rispettivamente nelle colonne Q ed R e nelle stesse righe da 8 a 18 ma potevono stare se celle libere anche nelle colonne J ed N alla righe 1289 ecc. ecc. adattando opportunamente le relative posizioni nelle istruzioni.
Supponendo che la riga in questione sia la 13° il primo if dice se il valore di J13 è maggiore del precedente salvato in Q13 allora colora la cella J13 di verde ed imposta il suono numero 10.
Il secondo if analogamente se minore colora la cella J13 di rosso ed imposta il suono numero 11.
5° Comunque la cella viene evidenziata e si procede a salvare i valori della cella J13 ed N13 rispettivamente in Q13 ed R13 per il controllo del prossimo arrivo.
Quindi si procede alla generazione del suono.
5° ho inserito in testa al Modulo2 queste tre righe perché dichiarazione private
Code:
Private Declare Function sndPlaySound Lib "WINMM.DLL" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
Const SND_ASYNC = &H1
6° ho inserito nel Modulo2 la routine GeneraSuono
Code:
Public Sub GeneraSuono(ByVal TipoSuono As Long)
Dim P As Long, SoundName As String
Select Case TipoSuono
Case 1
SoundName = "c:\windows\media\Chimes.wav"
Case 2
SoundName = "c:\windows\media\Chord.wav"
Case 3
SoundName = "c:\windows\media\Ding.wav"
Case 4
SoundName = "c:\windows\media\Notify.wav"
Case 5
SoundName = "c:\windows\media\Recycle.wav"
Case 6
SoundName = "c:\windows\media\Ringing.wav"
Case 7
SoundName = "c:\windows\media\Ringout.wav"
Case 8
SoundName = "c:\windows\media\Start.wav"
Case 9
SoundName = "c:\windows\media\Tada.wav"
Case 10
SoundName = "c:\Programmi\MemoRex\Suoni\Fanfare.wav"
Case 11
SoundName = "c:\Programmi\MemoRex\Suoni\Allarme.wav"
Case Else
'Beep
Exit Sub
End Select
P = sndPlaySound(SoundName, SND_ASYNC)
End Sub
Tenere presente che le precedenti due fasi (5° e 6°) devono risiedere sullo stesso modulo.
7° Esiste nel Modulo3 la seguente routine da me ancora non usata ne provata :
Code:
Public Sub AnnullaLinkList()
Dim Links As Variant
Links = ActiveWorkbook.LinkSources(xlOLELinks)
If Not IsEmpty(Links) Then
For i = 1 To UBound(Links)
ActiveWorkbook.SetLinkOnData Links(i), ""
Next i
End If
End Sub
che se attivata chiude tutti i canali DDE aperti tramite quei doppi apici nell’istruzione ActiveWorkbook.SetLinkOnData Links(i), ""
Credo che ho detto tutto , che sia stato chiaro e spero che possa essere di aiuto a qualcuno.