Pivot excel ok server - errore client

giovedì 28 marzo 2013 - 17.02

jjchuck Profilo | Senior Member

ciao a tutti
...si son sempre qui
ho provato diverse soluzioni per fare pivot in asp...ma per ora il metodo che allego mi basta (riesco cmq ad ottenere pivot dinamiche/programmabili).
sottolineo che funziona se lo utilizzo da server ...invece restituisce errore da client:
System.Runtime.InteropServices.COMException: Eccezione da HRESULT: 0x800AC472

...ho letto che in pratica il server "non sa come gestire la chiamata" e che bisogna implementare IMessageFilter per gestire la cosa...
ora non so bene cosa significhi e nemmeno se davvero sia la soluzione però spero che qui mi sappiate aiutare...dopo aver realizzato un programmino che va non posso condividerlo nel mio sito...capirete la delusione...

cmq uso excel 2003,vs2010,W Xp....
ho aggiunto il riferimento Interop.Excel.dll
...di seguito il codice funzionante...sto impazzendo
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

0v3rCl0ck Profilo | Guru

Il problema è che stai eseguendo del codice lato server che apre l'applicazione excel sul server non sul client... tutte le istruzioni che esegui lato server rimangono lato server, quindi alla meglio ti saresti ritrovato con un excel aperto lato server, non di certo lato client, i comandi che puoi inviare al client possono essere comandi HTTP, HTML o al più JAVASCRIPT.

Per come hai progettato questo software, dovresti distribuire sia la parte client che la parte server, e il client deve avere anche excel installato.

Per non buttare via tutto quello che hai fatto, posso consigliarti di fare, è di mantenere il file generato, creare uno stream dallo stesso (oppure al posto di SaveAs esiste un metodo che ritorna uno stream?), e darlo in risposta al client web, che potrà salvarselo su disco e aprirlo. Credo sia anche possibile aprirlo direttamente se nella risposta che dai al client dici anche che tipo di file è, modificando il mime type nel formato del file tipo "application/excel" (http://www.webmaster-toolkit.com/mime-types.shtml).

Per riuscire a ritornare un file al client, dovresti crearti un generic handler ashx (http://www.dotnetperls.com/ashx) che ti da la possibilità di manipolare il Response e appunto cambiare gli attributi tipo il ContentType, e utilizzare ad esempio il metodo context.Response.WriteFile("c:\Tmp\Report3.xls") per scrivere il file appena generato. Ovviamente non utilizzare un nome file univoco, ma crea il file chiedendo al sistema operativo un nome temporaneo univoco (http://msdn.microsoft.com/it-it/library/system.io.path.gettempfilename.aspx oppure http://msdn.microsoft.com/it-it/library/system.io.path.getrandomfilename.aspx).



-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

grazie per la risposta...ora è chiaro che quello che faccio è concettualmente impossibile o meglio errato...

però non riesco a capire bene come implementare quei metodi...

il codice che ho postato è ridotto all'osso...l'utente decide quali campi pivotare (dopo aver eventualmente pure filtrato i record) e se fare somma,conta...ecc...
...percui quando esporta viene passata la stringa a microsoftquery e generata la pivot e salvata su una cartella temporanea....

ora...io proprio non so come muovermi in base ai tuoi aiuti...sono un po stordito anche data l'ora...
...non cè un esempio...per me è un po complessa la cosa...non voglio che mi fai il lavoro...ma uno spunto...davvero so sfinito

ps: dimenticavo che in ditta abbiamo tutti xls percui almeno li ci siamo

0v3rCl0ck Profilo | Guru

ok diciamo che il discorso del generic handler si può anche farne a meno, è utile per gestire la cosa a servizio e per avere un buon design applicativo, ma non è obbligatorio, puoi anche partire da una cosa così:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Ti ho allegato anche un esempio completo funzionante.

Ciao!

-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

grazie mille...stasera gli do un'occhiata...
spero di non impazzire:)


...certo che non si finisce mai


domani ti dirò se mi è stato utile...

buona serata

jjchuck Profilo | Senior Member

ho provato ma lato client ho lo stesso errore: System.Runtime.InteropServices.COMException: Eccezione da HRESULT: 0x800AC472
sul server mi restituisce la tabella pivot ma poi nel browser mi dice :Il processo non può accedere al file 'c:\Tmp\Report.xls' perché è in uso da un altro processo.
...questo è li codice che ho modificato in base alle tue specifiche...almeno credo...si trattava di copiare la tua funzione...spero di aver fatto bene
RETTIFICO**************************************************************************************************************
HO INSERITO IL TUO CODICE PARO PARO NEL MIO SITO WEB E FUNZIONA: mi trasferisce il file lato client...
percui sono un coj... MA NON CAPISCO PERCHE MODIFICANDO LA MIA ROUTINE (ridotta sempre all'osso) NON VA

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

in C#
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

cmq debbo di che su sto forum siete i numeri uno...per lo stesso problema ho letto su forum di ogni tipo....le peggio elucubrazioni

0v3rCl0ck Profilo | Guru

credo tu venga dal buon vecchio visual basic 6.0 o sbaglio?

//pulisco
ptTable = null;
ptCache = null;
xlWSheet = null;
xlWBook = null;
xlApp = null;

perchè in .net non si distruggono più gli oggetti facendo semplicemente = null, e sopratutto i vari handle facendo così rimangono attivi, fino a quando eventualmente non viene chiamato il finalizer dell'oggetto e li forse viene chiuso l'handle (dipende dall'implementazione dell'oggetto).

Detto questo prova a chiamare il metodo .Dispose() su ogni oggetto che lo implementa, prima di settarli a null, specialmente sull'oggetto xlWBook, perchè ho il presentimento che sia lui che tenga un handle attivo sul file appena scritto.


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

si vengo da li...o meglio da ms access...che è uguale (anche se non sono un programmatore purtroppo)

cmq qualche miglioria cè perchè sul server non ho piu errori...ma da un altro pc
System.Runtime.InteropServices.COMException: Eccezione da HRESULT: 0x800AC472

l'errore è qui...
Dim xlWBook As Excel.Workbook = xlApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet)

0v3rCl0ck Profilo | Guru

intanto non usare lo stesso nome file come ti dicevo, ma fai in modo di fartene dare uno temporaneo dal sistema operativo con i comandi che ti avevo passato e vediamo che succede...

EDIT: controlla anche quanti eseguibili excel.exe vedi nella taskbar, sinceramente non ho mai utilizzato questo approccio, e penso che venga eseguita proprio l'applicazione excel in background, e che quest'ultima vada chiusa prima di terminare l'operazione, altrimenti ho paura che rimanga appesa creandoti grossi problemi di memory leak, sia per l'eseguibile appeso che per tutti gli handle del sistema operativo verso i file creati dall'excel.


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

Dim nomefile = Path.GetRandomFileName()
xlWBook.SaveAs("c:\Tmp\" & nomefile & ".xls")
...
ResponseFile("c:\Tmp\" & nomefile & ".xls")

Private Sub ResponseFile(ByVal filename As String)
Response.Clear()
Dim cd = New ContentDisposition()
cd.FileName = "MyPivot.xls"
.....ecc

System.Runtime.InteropServices.COMException: Eccezione da HRESULT: 0x800AC472
sempre questo...però sul server funziona

0v3rCl0ck Profilo | Guru

dai le permission everyone full access alla cartella "c:\Tmp\"

dove stai facendo girare il sito? IIS? IIS Express? Development server?


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

IIS V5.1
...ho windows xp...percui clik dx -protezione-poi?


ps: però ho inserito il tuo esempio sotto la stessa Tmp...e funziona...non capisco

0v3rCl0ck Profilo | Guru

il fatto è che il mio esempio non utilizza per niente l'oggetto excel application, ma semplicemente restituisce il file excel già creato...il problema sembra essere nella creazione del file.

in che punto preciso ti da l'errore, a che riga?

hai provato a mettere le .Dispose() come ti dicevo?

vedi degli eseguibili tipo excel.exe sul server, mentre durante o cmq dopo l'esecuzione della pagina dal client?

da server funziona digitando http://localhost/....? fai una prova con http://nome-server/... e dimmi come va

una delle differenze tra eseguire la pagina da client o server, forse può essere con che utente IIS viene eseguito il codice, bisogna capire cosa fa quell'oggetto "excel application" se una volta istanziato crea a sua volta altri application domain tipo lanciare l'esecuibile di excel, e questo probabilmente può essere fatto solo da certi tipi di utente...


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

si ho provato la dispose (anche close)...
ed in effetti come ti segnalavo l'errore è qui...nella generazione dell'excel...
Dim xlWBook As Excel.Workbook = xlApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet)

....cmq accetto come risolto perchè tanto la strada è quella che mi hai piu che suggerito...

un ultima cosa che non centra...

protected void Page_Load(object sender, EventArgs e)
{
CheckBoxList1.AutoPostBack = true;
CheckBoxList1.SelectedIndexChanged += new EventHandler(CheckBoxList1_SelectedIndexChanged);

}

non riesco a convertire la seconda riga in vb.net ...mi dice di usare l'evento raiseEvent...quindi di gestire l'evento...non capisco come anche se mi son documentato sono confuso

*********
http://nome-server/... ho fatto questa prova (anziche lanciare da clik dx visualizza nel browser) ed in effetti sul server da errore sempre nello stesso punto che dava da client...la sai lunga

0v3rCl0ck Profilo | Guru

>si ho provato la dispose (anche close)...
>ed in effetti come ti segnalavo l'errore è qui...nella generazione
>dell'excel...
>Dim xlWBook As Excel.Workbook = xlApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet)

prova a capire bene cosa succede quando esegui questa istruzione, e se eventualmente fa qualcosa per cui hai bisogno di permessi di esecuzione diversi.

>
>....cmq accetto come risolto perchè tanto la strada è quella
>che mi hai piu che suggerito...

ok grazie così chiudiamo il thread, poi eventualmente se trovi qualcosa da chiedere di più specifico ne apri un altro, ma nell'eventualità ti consiglio di preparare un progetto web di esempio con le stesse istruzione senza la configurazione, ma che restituisce lo stesso identico errore, e poi ce lo puoi postare come allegato file e magari riusciamo a darti un aiuto più mirato.

>
>un ultima cosa che non centra...
>
>protected void Page_Load(object sender, EventArgs e)
> {
> CheckBoxList1.AutoPostBack = true;
>CheckBoxList1.SelectedIndexChanged += new EventHandler(CheckBoxList1_SelectedIndexChanged);
>
> }
>
>non riesco a convertire la seconda riga in vb.net ...mi dice
>di usare l'evento raiseEvent...quindi di gestire l'evento...non
>capisco come anche se mi son documentato sono confuso

protected void Page_Load(object sender, EventArgs e) { CheckBoxList1.AutoPostBack = true; CheckBoxList1.SelectedIndexChanged += CheckBoxList1_SelectedIndexChanged; } private void CheckBoxList1_SelectedIndexChanged(object sender, EventArgs e) { throw new NotImplementedException(); }

così?

>
>*********
>http://nome-server/... ho fatto questa prova (anziche lanciare
>da clik dx visualizza nel browser) ed in effetti sul server da
>errore sempre nello stesso punto che dava da client...la sai
>lunga

bene ora ai anche modo di riprodurre il problema in locale, deve essere collegato all'utente che esegue il codice lato server, in dettaglio l'utente che utilizza IIS per eseguire il codice, e la prova più semplice è provare semplicemente a metterci il tuo utente con diritti di amministrazione e vedere se così funziona, e da li ci lavori per capire come mai ha bisogno di tutta quella libertà, ma credo sia perchè è un oggetto interattivo, e si aspetta di girare con un utente non di servizio.


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

si hai ragione...postero un esempio...tanto ora sto facendo 3 cose contemporaneamente e male percui ci tornero senz'altro...cho lavorato e mi dispiace abbandore un progettino che fa le pivot dinamicamente...per me è già tanto...
percui mi faro risentire presto

...per il codice no...in realta il codice completo è questo
protected void Page_Load(object sender, EventArgs e)
{
CheckBoxList1.AutoPostBack = true;
CheckBoxList1.SelectedIndexChanged += new EventHandler(CheckBoxList1_SelectedIndexChanged);

}

private void CheckBoxList1_SelectedIndexChanged(object sender, EventArgs e)
{
ListBox1.Items.Clear();
foreach (ListItem li in CheckBoxList1.Items)
{
if (li.Selected)
{
ListBox1.Items.Add(new ListItem(li.Text, li.Value));
}
}
}
}

e ad ogni selezione della checkboxlist inserisce un valore nella listbox non mantenendo l'indice (percui inserisci i valori con l'ordine che vuoi)...cosa utile perchè in poche righe fa un gran lavoro (almeno credo)

0v3rCl0ck Profilo | Guru

mi fa sorridere, perchè ho lavorato anni anche in vb e non ricordavo più come fare, ho dovuto riguardarci, questo un po' dimostra che vb.net è meno mnemonico di c# perchè non mi sarei proprio ricordato che si faceva così:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

ca...c'ero quasi ma non ero sicuro
grazie mille

a presto

0v3rCl0ck Profilo | Guru

accetta una risposta che chiudiamo il thread, grazie!


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

ciao
spero tutto bene

ho postato il mio progetto ridotto al nulla per replicare l'errore come mi consigliavi...

ed ineffetti è sull'esecuzione di excel.exe...se ho capito bene...


spero avrai tempo di dargli un'occhiata perchè con le conoscenze che ho e googolando non ho capito se non si può fare (anche se mi pare strano)

0v3rCl0ck Profilo | Guru

non vedo il progetto, dove l'hai postato?


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/

jjchuck Profilo | Senior Member

qui
http://www.dotnethell.it/forum/messages.aspx?ThreadID=42896

ne ho aperto un altro...mi avevi dato ottimi consigli...utili soprattutto...
mi sembrava piu corretto aprire un altro post

0v3rCl0ck Profilo | Guru

ok appena ho un attimo ci guardo :)


-------------------------------------------------------
Michael Denny
Lead Software Developer & Solutions Architect
http://blogs.dotnethell.it/Regulator/
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5