|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Jan 2004
Città: Monza
Messaggi: 36
|
[VBA] DDE+Excel
Ciao a tutti, spero che l'argomento non sia già stato affrontato, se così è mi scuso per il search superficiale...
![]() Ho una cella con un datafeed realtime che cambia ogni secondo. Vorrei in un intervallo delta_t (ad esempio 3 min) registrare il valore a t=0 e a t=3 ed il valore minimo e massimo. Ho provato con le semplici formule di excel, ma riesco esclusivamente a ricopiare il valore della formula, che quindi continua a variare nel tempo. In poche parole vorrei una storicizzazione del valori suddetti. Sapete darmi qualche suggerimento o darmi qualche link utile? Grazie e buona serata. |
![]() |
![]() |
![]() |
#2 | |
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3209
|
Quote:
Anzitutto un consiglio : rinomina il thread con un bel [ Excel VBA ] iniziale. Non vorrei che ti chiudessero la discussione. ![]() Una precisazione : oltre al valore iniziale/finale/max/min lo storico prevede la registrazione dei valori ad ogni secondo sullo stesso Foglio in cui è presente la cella DDE ? |
|
![]() |
![]() |
![]() |
#3 |
Member
Iscritto dal: Jan 2004
Città: Monza
Messaggi: 36
|
Mi scuso per la niubbaggine e per non aver letto le regole del forum, ma non riesco a modificare il titolo, prego i moderatori di farlo per me.
Lo storico che voglio creare non richiede la memorizzazione dato per dato ma esclusivamente i valori di min, max, iniziale e finale con timeframe definito. cella DDE x [cambia continuamente] time t=iniz. min max t=finale 3 X0 Xmin Xmax X3- 6 X3+ Xmin Xmax X6- 9 .................................................... 12 ..................................................... |
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3209
|
Quote:
Il programma deve generare una tabella, sempre su Foglio1, e ogni 3 minuti riportare i 4 valori [ inizio / min / max / fine ] rilevati sui 180 ( 3x60 ) secondi di ogni intervallo. Corretto ? |
|
![]() |
![]() |
![]() |
#5 |
Member
Iscritto dal: Jan 2004
Città: Monza
Messaggi: 36
|
Corretto!
Sto cercando nelle funzioni "importazione dati" ma mi sa che non ci cavo nulla di buono... |
![]() |
![]() |
![]() |
#6 |
Member
Iscritto dal: Jan 2004
Città: Monza
Messaggi: 36
|
Dopo svariati tentativi sono arrivato a questa macro, dal sito di Microsoft
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 Quello che fa è rilevare il cambiamento della cella DDE e, in corrispondenza di tale cambiamento, fa partire la macro "LinkChange". Ora si tratta dunque di strutturare la macro LinkChange in modo da ricopiare i dati che intercetta nella colonna di fianco. Da lì poi con le formule normali si riesce a rispondere alle esigenze che ho citato nel primo post (min,max,iniziale,finale) Qualcuno è in grado di aiutarmi a scrivere questa macro di copia valori? |
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3209
|
Sei riuscito con quel metodo ?
Io invece sono riuscito a risolvere il tuo quesito con qualche chiamata alle API ( ho chiamato da Excel il Timer di sistema... ), un paio di Sub ,e un bell'Array per i valori... ![]() |
![]() |
![]() |
![]() |
#8 |
Member
Iscritto dal: Jan 2004
Città: Monza
Messaggi: 36
|
Fra 30 minuti ti posto tutto
![]() Edit: prima del previsto Dim bRunNow As Boolean Sub Test1() With ActiveWorkbook bRunNow = .Worksheets("Foglio1").Range("C1").Value If bRunNow Then .SetLinkOnData "FDF|Q!'F.MI;Last'", "Test2" Else .SetLinkOnData "FDF|Q!'F.MI;Last'", "" End With End Sub Sub Test2() ddedati = "C3:C3" TWS = "Foglio1" SWS = ActiveSheet.Name Range(ddedati).Copy Sheets(TWS).Select If Range("C3").Value < Range("F2").Value Or Range("F2").Value = 0 Then Range("F2").Value = Range("C3").Value 'Calcolo Min If Range("C3").Value > Range("E2").Value Or Range("E2").Value = 0 Then Range("E2").Value = Range("C3").Value 'Calcolo Max Range("G2").Value = Range("C3").Value 'Calcolo Current Sheets(SWS).Select End Sub Sub ButtonTest() Test1 End Sub Sub Restarta() DeltaT = "00:03:00" CellaFlag = "N1" dati = "E2:G2" DWS = "Foglio1" CWS = ActiveSheet.Name Range(dati).Copy Sheets(DWS).Select Range("J65536:L65536").End(xlUp).Offset(1, 0).Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Application.CutCopyMode = False Range("G2").Copy Range("I65536").End(xlUp).Offset(1, 0).Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Application.CutCopyMode = False Range(dati).Select Selection.ClearContents Sheets(CWS).Select If Range(CellaFlag).Value = 0 Then Range(CellaFlag).Interior.ColorIndex = xlNone Exit Sub End If Application.OnTime Now + TimeValue(DeltaT), "Restarta" Range(CellaFlag).Interior.ColorIndex = 3 End Sub ![]() Se hai qualche domanda specifica fai pure... Mi piacerebbe sapere anche la tua soluzione, visto che cmq questa non mi soddisfa appieno. Ciao e buona serata! Ultima modifica di Kimiko : 13-03-2008 alle 20:36. |
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3209
|
Quote:
![]() 1. Ho un file Excel, che può contenere anche solo un foglio, Foglio1. 2. Foglio1 è organizzato come segue : - Cella A1 : contiene i valori DDE. - Colonne da B a F : Tabella valori ( 1 nuova riga ogni intervallo -> 180 sec. ). - 2 CommandButton : Start e Stop registrazione valori. Vedi figura : ![]() 3. Codice che esegue il CommandButton START : Codice:
Private Sub CommandButton1_Click() Sheets("Foglio1").Range("C2:F4").ClearContents Sheets("Foglio1").Range("C2").FormulaR1C1 = Sheets("Foglio1").Range("A1").Value intervallo = 180 'SECONDI contaSecondi = 0 contaIntervalli = 2 CommandButton1.Enabled = False ReDim arrayValori(0) StartTimer End Sub Codice:
Private Sub CommandButton2_Click() EndTimer CommandButton1.Enabled = True End Sub Codice:
Public intervallo As Integer Public contaIntervalli As Integer Public contaSecondi As Integer Public arrayValori() As Double Public TimerID As Long Public TimerSeconds As Single Public Declare Function SetTimer Lib "user32" ( _ ByVal HWnd As Long, _ ByVal nIDEvent As Long, _ ByVal uElapse As Long, _ ByVal lpTimerFunc As Long) As Long Public Declare Function KillTimer Lib "user32" ( _ ByVal HWnd As Long, _ ByVal nIDEvent As Long) As Long Public Sub StartTimer() TimerSeconds = 1 'Intervallo di Intervento Timer in Secondi. TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc) End Sub Public Sub EndTimer() On Error Resume Next KillTimer 0&, TimerID End Sub Public Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, _ ByVal nIDEvent As Long, ByVal dwTimer As Long) AGG_ARRAY_VALORI (Sheets("Foglio1").Range("A1").Value) If contaSecondi = intervallo Then Sheets("Foglio1").Range("F" & contaIntervalli).FormulaR1C1 = Sheets("Foglio1").Range("A1").Value Sheets("Foglio1").Range("D" & contaIntervalli).FormulaR1C1 = arrayValori(1) Sheets("Foglio1").Range("E" & contaIntervalli).FormulaR1C1 = arrayValori(UBound(arrayValori)) ReDim arrayValori(0) contaIntervalli = contaIntervalli + 1 contaSecondi = 0 End If If (contaSecondi - 1) Mod intervallo = 0 And contaIntervalli > 2 Then Sheets("Foglio1").Range("C" & contaIntervalli).FormulaR1C1 = Sheets("Foglio1").Range("A1").Value End If contaSecondi = contaSecondi + 1 End Sub Public Sub AGG_ARRAY_VALORI(valore As Double) Dim valRedim As Long valRedim = UBound(arrayValori) + 1 ReDim Preserve arrayValori(valRedim) arrayValori(valRedim) = valore Dim Temp As Double Dim i As Long Dim j As Long For j = 2 To UBound(arrayValori) Temp = arrayValori(j) For i = j - 1 To 1 Step -1 If (arrayValori(i) <= Temp) Then GoTo 10 arrayValori(i + 1) = arrayValori(i) Next i i = 0 10 arrayValori(i + 1) = Temp Next j End Sub ![]() |
|
![]() |
![]() |
![]() |
#10 |
Member
Iscritto dal: Jan 2004
Città: Monza
Messaggi: 36
|
L'aspetto è professionale, più tardi (o domani, meglio
![]() Grazie comunque. |
![]() |
![]() |
![]() |
#11 | ||||
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3209
|
Quote:
Quote:
Quote:
Chiaramente, se devi costruire un'applicazione complessa che fa pesante uso dei Timer, il mio consiglio è di utilizzare VB6 o VB NET, che offrono un ottimo supporto all'interazione con Excel. Quote:
![]() |
||||
![]() |
![]() |
![]() |
#12 |
Junior Member
Iscritto dal: Jan 2009
Messaggi: 10
|
Ciao marco,
Per quanto riguarda il DDE non l'ho implementato io ma è un collegamento alla banca dati tramite un programma da loro foirnito. L'azzeramento è dovuto al loro collegamento e non è 1 problema specifico dell'utenza (succede raramente, è solo un istante e non c'e perdita di dati..... solo che mi sballa il grafico ![]() Le celle DDE sono già 2 (ne ho aggiunta una io alla tua macro) e diventerebbero 6 ![]() ![]() ![]() |
![]() |
![]() |
![]() |
#13 | |
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3209
|
Quote:
![]() Per quanto riguarda l'ultimo problema, ossia la temporizzazione di una Macro ( Sub o Function ) si può risolvere semplicemente con le stesse chiamate API del mio esempio precedente. In questo caso il codice necessario sarà qualcosa di simile a questo : > In un Modulo : Codice:
Public TimerID As Long Public TimerSeconds As Single Public Declare Function SetTimer Lib "user32" ( _ ByVal HWnd As Long, _ ByVal nIDEvent As Long, _ ByVal uElapse As Long, _ ByVal lpTimerFunc As Long) As Long Public Declare Function KillTimer Lib "user32" ( _ ByVal HWnd As Long, _ ByVal nIDEvent As Long) As Long Public Sub StartTimer() TimerSeconds = 1 'Intervallo di Intervento Timer in Secondi. TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc) End Sub Public Sub EndTimer() On Error Resume Next KillTimer 0&, TimerID End Sub Public Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, _ ByVal nIDEvent As Long, ByVal dwTimer As Long) Dim adesso As String adesso = Format(Now, "yyyy/mm/dd hh:mm:ss") Sheets("Foglio1").Range("A1").FormulaR1C1 = adesso If CDate(adesso) = "2009/01/12 14:40:00" Then 'Lancio la macro desiderata : MACRO End If End Sub Public Sub MACRO() MsgBox "MACRO Lanciata." End Sub Codice:
Private Sub cmd_start_Click() cmd_start.Enabled = False StartTimer End Sub Codice:
Private Sub cmd_stop_Click() EndTimer cmd_start.Enabled = True End Sub ![]() |
|
![]() |
![]() |
![]() |
#14 |
Junior Member
Iscritto dal: Jan 2009
Messaggi: 10
|
Grazie, sempre molto gentile
![]() ora provo a mettere in pratica i tuoi suggerimenti ......... se per un po non mi senti non preoccuparti, sto sbattendo la testa ![]() ![]() ciao pupic Ps: ora ho capito che l' API non è l' "Associazione Programmatori Italiani" ![]() ![]() ![]() |
![]() |
![]() |
![]() |
#15 |
Junior Member
Iscritto dal: Jan 2009
Messaggi: 10
|
Ciao Marco, ...... ancora io
![]() volevo allegare il file del foglio completo dei 3 titoli x un tuo consiglio ma anche zippato supera la dimensione consentita ![]() Volevo chiederti informazioni sugli array (faccio riferimento al range "D" = arrayValori(1)) : nella tua macro, dove sono specificate le variabili dell'array ? E dove è specificato che sono relative alla cella A1 ? Se ho fatto una domanda stupida ![]() ![]() |
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3209
|
Quote:
Codice:
Public arrayValori() As Double ![]() Qui : Codice:
AGG_ARRAY_VALORI (Sheets("Foglio1").Range("A1").Value) |
|
![]() |
![]() |
![]() |
#17 |
Junior Member
Iscritto dal: Jan 2009
Messaggi: 10
|
Grazie per i chiarimenti
![]() ciao ![]() |
![]() |
![]() |
![]() |
#18 |
Junior Member
Iscritto dal: Jan 2009
Messaggi: 11
|
ciao,
ho letto il tuo post "Dati real time x excel " ma sopratutto questo "[VBA] DDE+Excel " un paio di anni fa ci ho perso un tot di tempo, dovendo poi rinunciare, per mancanza risultati, per fare sostanzialmente la stessa cosa che cercavi di far tu... e mi pare che avete in qualche modo risolto io ho in una cella di excel i dati che arrivano in realtime, ( pz, o, h, l, c, ) tutti in una riga quello che non sono mai riuscito a fare, e che mi servirebbe e che ogni minuto quella riga si "fissasse" con tutti i suoi valori e riprendesse il flusso di dati alla riga sotto, e cosi via per tutta la giornata ( il problema di recuperare dati persi o storici per ora non mi serve, mi basta il realtime della giornata strutturato nel modo che ho cercato di spiegarti ) mi potete aiutare? qualcuno e' riuscito a costruire un foglio excel che fa una roba simile? mi fareste un enorme favore,,, sono zero a programmare, e non saprei neanche costruire una macro copiando il codice postato da MarcoGG intanto grazie cmq ciao marco |
![]() |
![]() |
![]() |
#19 | |
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3209
|
Quote:
Da quello che ho capito, ogni minuto vorresti registrare i valori sulla stessa riga in cui sta la cella DDE ( o le celle DDE ), e poi spstare la riga-DDE verso il basso. Poco pratico, forse. Non sarebbe meglio copiare i valori su una nuova riga ad ogni scatto di clock, e mantenere la DDE sempre al suo posto ? |
|
![]() |
![]() |
![]() |
#20 |
Junior Member
Iscritto dal: Jan 2009
Messaggi: 10
|
Ciao Marco&Marco …… tutti Marco
![]() La prima macro di Marco funziona egregiamente, devi solo partire da due soli dati DDE e cioè il “prezzo ultimo” e il volume, il resto lo fa la macro. Capisco la tua necessità e la difficoltà di applicare la macro, anche se basta copiarla; ci ho lavorato anch’io parecchio partendo a studiare il VBA da zero (adesso non sono tanto più in là …… forse a 0,5 ![]() ![]() ![]() con gli array sono ancora in pieno oceano Atlantico su una barca a remi ![]() Dim adesso As String adesso = Format(Now, "yyyy/mm/dd hh:mm:ss") Sheets("Foglio1").Range("A1").FormulaR1C1 = adesso If CDate(adesso) = "2009/01/12 14:40:00" Then.... L’ho posizionato ovunque nella tua prima macro ma senza risolvere ![]() ![]() Buona domenica a tutti Pupic |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 19:59.