PDA

View Full Version : [VB.NET]programma in background che legge file excel


radeon_snorky
06-11-2009, 23:55
come da titolo vorrei realizzare un piccolo programma che legge da un file excel alcune celle (sempre le stesse) e se trova una data a 6 mesi apre un messagebox contenente l'intera riga.
fine!
poi mi piacerebbe che potesse mandare una mail al posto del messaggio, ma questa è un'altra storia... iniziamo dalle cose semplici!

chi mi da uno spunto su come procedere?

grazie!

MarcoGG
07-11-2009, 10:36
"In background" significa che deve funzionare "di nascosto" ? ( tanto se vogliono chiudertelo, te lo chiudono comunque ) Oppure che deve funzionare senza che Excel sia installato... O cosa ?

radeon_snorky
07-11-2009, 12:07
"In background" significa che deve funzionare "di nascosto" ? ( tanto se vogliono chiudertelo, te lo chiudono comunque ) Oppure che deve funzionare senza che Excel sia installato... O cosa ?
scusa... ecco le precisazioni:
background -> in tray
i dati sarebbero in excel e il programma è installato su tutti i pc... ma non è obbligatorio utilizzarlo con il programma, è solo per comodità.
nel file excel ci sono indirizzi e date di "scadenza" ma possono essere messi anche su file di testo! pensavo alla comodità che si ha in excel di avere celle formattate e selezionabili facilmente, mentre un file di testo è meno "simpatico"

MarcoGG
07-11-2009, 12:26
i dati sarebbero in excel e il programma è installato su tutti i pc...

Beh, allora usa il metodo classico, che in presenza di Excel è anche il migliore, referenziando Microsoft.Office.Interop.Excel :

Dim appExcel As New Microsoft.Office.Interop.Excel.Application
appExcel.Visible = False
Dim WB As Microsoft.Office.Interop.Excel.Workbook = appExcel.Workbooks.Open(percorso & nomeFile)
Dim WS As Microsoft.Office.Interop.Excel.Worksheet = WB.Worksheets("Foglio1")
...
...
ecc...

radeon_snorky
07-11-2009, 12:41
Beh, allora usa il metodo classico, che in presenza di Excel è anche il migliore, referenziando Microsoft.Office.Interop.Excel :

Dim appExcel As New Microsoft.Office.Interop.Excel.Application
appExcel.Visible = False
Dim WB As Microsoft.Office.Interop.Excel.Workbook = appExcel.Workbooks.Open(percorso & nomeFile)
Dim WS As Microsoft.Office.Interop.Excel.Worksheet = WB.Worksheets("Foglio1")
...
...
ecc...

mi stai dicendo che posso "portare" excel in vb.net? così da lavorare su celle e formati come se usassi vba?

MarcoGG
07-11-2009, 16:33
mi stai dicendo che posso "portare" excel in vb.net? così da lavorare su celle e formati come se usassi vba?

Puoi gestire da VB.NET un'applicazione Excel, avendo a disposizione praticamente tutte le proprietà e i metodi che trovi in Excel VBA.
Certo, non puoi fare copia-incolla da VBA a VB.NET e pretendere che funzioni tutto... ;)

radeon_snorky
07-11-2009, 16:47
Puoi gestire da VB.NET un'applicazione Excel, avendo a disposizione praticamente tutte le proprietà e i metodi che trovi in Excel VBA.
Certo, non puoi fare copia-incolla da VBA a VB.NET e pretendere che funzioni tutto... ;)

no, no.. lo immagino!
però per quel che devo fare io il copia-incolla lo posso fare di un buon 85-90%
...
ma siamo sempre alle solite: c'è bisogno di uno spunto, un "cicchetto", un bottarella nella giusta direzione... altrimenti la mia incapacità mi lascia al palo!

dove mi posso leggere guide ed esempi?

radeon_snorky
15-11-2009, 08:54
ho cercato in lungo e in largo ma non ho trovato nulla che potesse fare al caso mio... perché non ho trovato nulla? per 2 motivi... non so cosa cercare e tra i millemila link c'è tanto materiale in inglese...
comunque ho seguito questa strada:
1) come mi hai suggerito ho referenziato Microsoft.Office.Interop.Excel e aggiunto le tue righe di codice.
2) ho definito un array formato dal range che contiene TUTTI i dati che mi servono (2 colonne per 40 righe)
3) creato un ciclo for next per leggere le celle e mostrare un messaggio al verificarsi di una condizione (per ora è data <> da now)

ora:
- è giusto creare una array con tutti i valori? oppure devo suddividerlo separando le date dai testi? se dovessi applicare un array a molte celle, quanto può essere grande l'array prima di diventare "pesante, lento e ingestibile", o non c'è problema?
- altra cosa, ma legata alla prima, avendo un array di testi&date, la condizione che vorrei verificare è now() + 180 >= della data ma ho 2 difficoltà, dà errore sui testi (so che è semplice risolvere... tipo aggiungere una condizione "madre" che screma i testi... giusto? provo? o c'è di meglio?), e poi non riesco ad aggiungere 180 alla data (devo forse convertire la data in numero, fare l'operazione e riconvertire in data?)
- la sub creata vorrei che fosse indipendente dall'utente, deve essere gestito da un timer e solo secondariamente dalla pressione di un tasto. ho provato a dichiarare la sub pubblica ma mi da errore... non ti posso dire l'errore perché il programmino ce l'ho in ufficio! adesso riprovo a farlo a casa...

helpatemi :)

MarcoGG
15-11-2009, 11:15
- è giusto creare una array con tutti i valori? oppure devo suddividerlo separando le date dai testi? se dovessi applicare un array a molte celle, quanto può essere grande l'array prima di diventare "pesante, lento e ingestibile", o non c'è problema?


No, non è corretto. Se hai detto che il tuo insieme di celle sono coppie <stringa, data>, dovrai avere un oggetto per ogni copia ( classe, structure, ecc... ). A quel punto fai un array di oggetti-coppia.
Impossibile rispondere alla seconda domanda.
L'array diventerà pesante, o pesantissimo e ingestibile ( come tutte le cose ), a seconda della bontà del tuo codice per farvi accesso in lettura/scrittura e ovviamente della mole di dati...


- altra cosa, ma legata alla prima, avendo un array di testi&date, la condizione che vorrei verificare è now() + 180 >= della data ma ho 2 difficoltà, dà errore sui testi (so che è semplice risolvere... tipo aggiungere una condizione "madre" che screma i testi... giusto? provo? o c'è di meglio?), e poi non riesco ad aggiungere 180 alla data (devo forse convertire la data in numero, fare l'operazione e riconvertire in data?)

Ecco perchè devi avere un array di oggetti-coppia. Ti risolvi dei gran casini inutili, prima che si presentino.
Per confronti tra intervalli di date usa i TimeSpan... ;)


- la sub creata vorrei che fosse indipendente dall'utente, deve essere gestito da un timer e solo secondariamente dalla pressione di un tasto. ho provato a dichiarare la sub pubblica ma mi da errore... non ti posso dire l'errore perché il programmino ce l'ho in ufficio! adesso riprovo a farlo a casa...


Non so cosa intendi per "indipendente dall'utente".
La "Sub pubblica" spesso va in errore perchè si fa riferimento ad oggetti della UI. Mai fare riferimento diretto a componenti UI, al di fuori del codice di una Form.

radeon_snorky
15-11-2009, 13:26
so che hai risposto.. ho letto tutto ma volevo mostrarti il codice come è ora con aggiunti i commenti:
Dim appExcel As New Microsoft.Office.Interop.Excel.Application
appExcel.Visible = True
Dim WB As Microsoft.Office.Interop.Excel.Workbook = appExcel.Workbooks.Open("C:\Users\max\Documents\cpi.xls")
Dim WS As Microsoft.Office.Interop.Excel.Worksheet = WB.Worksheets("Foglio1")
'devo dichiarare l'array nel modo giusto... e al momento non credo sia giusto
Dim scadenze(4, 1)
Dim indirizzi(4, 1)
Dim xlsRange(4, 2)
'dichiaro che il dato che mi serve è una data e l'indirizzo una stringa
Dim DataFine As Date
Dim indirizzo As String
'popolo l'array... quando riuscirò a capire qual'è...
xlsRange = WS.Range("A1:B4").Value
scadenze = WS.Range("B1:B4").Value
indirizzi = WS.Range("A1:A4").Value
'poi basta leggere dall'array
For Each DataFine In scadenze
'fare il calcolo
If DateDiff(DateInterval.Day, Now, DataFine) <= 180 Then
'nelle mie intenzioni vorrei conoscere la posizione
'del valore all'interno dell'array
'per usarlo per definire la cella che deve
'SOLO apparire nel messaggio
'quindi ne cerco l'index.... ma prima devo far bene le cose precedenti!!!!
Dim index As Integer
index = Array.IndexOf(scadenze, DataFine)
'poi uso index per prendere il valore della cella
index = index + 1
indirizzo = WS.Range("A" & index).Value
'e scrivo il messaggio
MsgBox("Attenzione! il " & DataFine & " scade la pratica! Riferimento: " & indirizzo)
End If
Next
WB.Close()
appExcel.Quit()
appExcel = Nothing
se volessi usare solo un array con le date, quindi monodimensionale, posso poi prendere la cella a fianco leggendo l'index della data nell'array? è quello che MI PARE il modo più semplice.... o no? lo so che mi hai già scritto... solo che adesso non riesco a scrivere altro... la signora esige di uscire di casa :D ciao e grazie

radeon_snorky
15-11-2009, 13:34
Non so cosa intendi per "indipendente dall'utente".
La "Sub pubblica" spesso va in errore perchè si fa riferimento ad oggetti della UI. Mai fare riferimento diretto a componenti UI, al di fuori del codice di una Form.
intendo dire che vorrei definire una procedura che posso richiamare tramite un timer... (il senso di "indipendente dall'utente") ed eventualmente richiamare la stessa procedura da un pulsante o da una voce di menu senza dover riscrivere il codice...
scappo, la signora ha un coltello in mano!!!!:cry:

MarcoGG
16-11-2009, 08:21
No, non ci siamo. Almeno, per come lo risolverei io...
Concettualmente può essere fatto in modo molto più pulito e diretto.

Anzitutto DateDiff(DateInterval.Day, DataFine, Now). Altrimenti ricevi differenze sempre negative...

Come già detto, preferisco mappare ogni coppia indirizzo-data con un oggetto :

Private Structure scadenza
Public indirizzo As String
Public data As DateTime
End Structure

A questo punto tutto ciò che segue è molto più lineare :

Dim appExcel As New Microsoft.Office.Interop.Excel.Application
appExcel.Visible = True
Dim WB As Microsoft.Office.Interop.Excel.Workbook = appExcel.Workbooks.Open(percorsoNomeFile)
Dim WS As Microsoft.Office.Interop.Excel.Worksheet = WB.Worksheets("Foglio1")

Dim scadenze As New List(Of scadenza)

For i As Integer = 1 To 4
Dim s As New scadenza
s.indirizzo = WS.Range("A" & i).Text
s.data = WS.Range("B" & i).Text
scadenze.Add(s)
Next

'Controllo
For Each s As scadenza In scadenze
If DateDiff(DateInterval.Day, s.data, Now) <= 180 Then
MsgBox("Attenzione! il " & s.data & " scade la pratica! Riferimento: " & s.indirizzo)
End If
Next

WB.Close()
appExcel.Quit()
appExcel = Nothing

;)

radeon_snorky
16-11-2009, 10:37
No, non ci siamo. Almeno, per come lo risolverei io...
Concettualmente può essere fatto in modo molto più pulito e diretto.

Anzitutto DateDiff(DateInterval.Day, DataFine, Now). Altrimenti ricevi differenze sempre negative...

;)

mmmm sicuro? ;)

MarcoGG
16-11-2009, 10:42
mmmm sicuro? ;)

Se le date sono inferiori a Now è come ho detto io. Se le date ( come nel tuo caso, ora che ci penso :p ) sono superiori va bene come hai fatto tu.

Per il resto, butta quel codice e fai come ti ho detto, ne hai solo vantaggi... ;)

radeon_snorky
16-11-2009, 10:47
Se le date sono inferiori a Now è come ho detto io. Se le date ( come nel tuo caso, ora che ci penso :p ) sono superiori va bene come hai fatto tu.

Per il resto, butta quel codice e fai come ti ho detto, ne hai solo vantaggi... ;)

ok, lo butto... però era proprio vomitevole?!??!?!

p.s. il processo excel rimane in memoria!!! uffiiiiiiiiiiii

MarcoGG
16-11-2009, 11:17
ok, lo butto... però era proprio vomitevole?!??!?!


A mio modo di vedere... SI ! :Puke: :asd:
Ma non prenderla come una critica "cattiva". Potrei postare codice VB6 scritto da me anni fa... Cose da far venire i brividi... :D


p.s. il processo excel rimane in memoria!!! uffiiiiiiiiiiii


E' un problema arci-noto. A volte Excel scompare dal Task Manager, a volte no. Il Processo Excel verrà chiuso comunque alla chiusura della Form, o dell'Application...
Ci sono diverse strategie per evitarlo. Puoi killare il processo...
Personalmente mi sto facendo una classe che gestisce in modo efficiente e definitivo i Processi Office da Interop, ma non penso certo di postarla qui... :nonsifa: :D

radeon_snorky
16-11-2009, 11:27
A mio modo di vedere... SI ! :Puke: :asd:
Ma non prenderla come una critica "cattiva". Potrei postare codice VB6 scritto da me anni fa... Cose da far venire i brividi... :D



E' un problema arci-noto. A volte Excel scompare dal Task Manager, a volte no. Il Processo Excel verrà chiuso comunque alla chiusura della Form, o dell'Application...
Ci sono diverse strategie per evitarlo. Puoi killare il processo...
Personalmente mi sto facendo una classe che gestisce in modo efficiente e definitivo i Processi Office da Interop, ma non penso certo di postarla qui... :nonsifa: :D
heheheh ok!
il fatto è che vorrei avviare il programma in esecuzione automatica e usare un timer per avviare lo "scan"... vabbè... avranno un processo excel in più... non è la fine del mondo.

grazie ancora delle dritte (e del codice) ieri ho passato un sacco di tempo fermo sul capitolo che parla di array su un manuale di francesco balena ma non c'ho cavato un ragno dal buco.... :(