2010-08-19 8 views
0

J'ai du code J'espère que quelqu'un pourra m'aider. Ce que j'essaie de réaliser est de convertir un formulaire XML Infopaths en un document Word 2007 en utilisant un fichier XSLT incorporé pour effectuer la transformation.System.IO.IOException en C# lors de la transformation xsl

code:

XPathNavigator nav = MainDataSource.CreateNavigator(); 
string fieldProject = nav.SelectSingleNode("//my:Project", NamespaceManager).Value; 
string fieldQuote = nav.SelectSingleNode("//my:QuoteNumber", NamespaceManager).Value; 
string fieldDate = nav.SelectSingleNode("//my:Date", NamespaceManager).Value; 


// Define variables for the word template to use and file to create 
string wordTemplateFilePath = @"\\2003server\common\OIF Proposals\TemplateFile\Interiors Letter Template.docx"; 
string wordPrintFilePath = @"\\2003server\common\OIF Proposals\Ben Johnson Ltd Furniture Proposal - " + fieldProject + " - " + fieldQuote + " - " + fieldDate + ".docx"; 

// Copy the template to create a new docx file 
File.Copy(wordTemplateFilePath, wordPrintFilePath, true); 

// Crack open the package 
Package packWordPrint = Package.Open(wordPrintFilePath, FileMode.Open, FileAccess.ReadWrite); 

// Retrieve the document.xml part of the new docx file 
PackagePart part = packWordPrint.GetPart(new Uri("/word/document.xml", UriKind.Relative)); 

// Retrieve the xsl to use to transform the InfoPath form into document.xml 
XslCompiledTransform trans = new XslCompiledTransform(); 
Stream xslTemplate = this.Template.OpenFileFromPackage("transform.xsl"); 
XmlReader xslTemplateReader = XmlReader.Create(xslTemplate); 
trans.Load(xslTemplateReader); 

// Create a StreamWriter to be able to write to the stream of the part 
using (StreamWriter partStream = new StreamWriter(part.GetStream(FileMode.Open, FileAccess.Write))) 
{ 
    // Transform the InfoPath form and save the XML into the stream for the part 
    trans.Transform(this.MainDataSource.CreateNavigator(), null, partStream); 

    // Close the stream of the part 
    partStream.Close(); 
} 

// Write changes to the package 
packWordPrint.Flush(); 

// Close the package 
packWordPrint.Close(); 

Et je reçois l'erreur suivante d'environ 1 à 8 fois:

System.IO.IOException 
The process cannot access the file '\\2003server\common\OIF Proposals\Ben Johnson Ltd Furniture Proposal - ABC123 - 123 - 2010-08-19.docx' because it is being used by another process. 
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 
    at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) 
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy) 
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean useAsync) 
    at MS.Internal.IO.Zip.ZipArchive.OpenOnFile(String path, FileMode mode, FileAccess access, FileShare share, Boolean streaming) 
    at System.IO.Packaging.ZipPackage..ctor(String path, FileMode mode, FileAccess access, FileShare share, Boolean streaming) 
    at System.IO.Packaging.Package.Open(String path, FileMode packageMode, FileAccess packageAccess, FileShare packageShare, Boolean streaming) 
    at System.IO.Packaging.Package.Open(String path, FileMode packageMode, FileAccess packageAccess) 
    at OIF_Order_Images.FormCode.CTRL31_5_Clicked(Object sender, ClickedEventArgs e) 
    at Microsoft.Office.InfoPath.Internal.ButtonEventHost.OnButtonClick(DocActionEvent pEvent) 
    at Microsoft.Office.Interop.InfoPath.SemiTrust._ButtonEventSink_SinkHelper.OnClick(DocActionEvent pEvent) 

Il doit y avoir un moyen judicieux de traiter ou de prévenir l'erreur, juste peut- » Je vais la contourner.

Je suppose que je ne dois pas fermer un flux quelque part correctement?

Tout pointeur/modification du code est grandement apprécié.

Un grand merci

Rich

Répondre

0

Il est préférable d'utiliser using pour vous assurer que l'emballage est fermé:

using (Package packWordPrint = Package.Open(wordPrintFilePath, FileMode.Open, FileAccess.ReadWrite)) 
{ 
    ... 
} 

et supprimez l'instruction packWordPrint.Close();.

+0

Brilliant, merci la suggestion – Richard

0

Refactoriser votre code pour être un peu plus efficace et plus déterministe sur les fermetures de fichiers. Cela devrait aider. note: j'ai ré-factorisé dans l'éditeur de SO donc il pourrait y avoir des fautes de frappe, accolades manquantes etc.

De plus, je ne savais pas quoi d'autre vous utilisiez pour PackWordPrint mais doit-il vraiment être ouvert ReadWrite? On dirait que vous êtes juste en train de lire, ReadOnly sera donc plus intelligent et vous n'aurez pas besoin d'appeler Flush à la fin.

XPathNavigator nav = MainDataSource.CreateNavigator(); 
string fieldProject = nav.SelectSingleNode("//my:Project", NamespaceManager).Value; 
string fieldQuote = nav.SelectSingleNode("//my:QuoteNumber", NamespaceManager).Value; 
string fieldDate = nav.SelectSingleNode("//my:Date", NamespaceManager).Value; 

// Retrieve the xsl to use to transform the InfoPath form into document.xml 
Stream xslTemplate = this.Template.OpenFileFromPackage("transform.xsl"); 
XmlReader xslTemplateReader = XmlReader.Create(xslTemplate); 

XslCompiledTransform trans = new XslCompiledTransform(); 
trans.Load(xslTemplateReader); 

// Define variables for the word template to use and file to create 
string wordTemplateFilePath = @"\\2003server\common\OIF Proposals\TemplateFile\Interiors Letter Template.docx"; 
string wordPrintFilePath = string.Format(@"\\2003server\common\OIF Proposals\Ben Johnson Ltd Furniture Proposal - {0} - {1} - {2}.docx",fieldProject, fieldQuote,fieldDate); 

// Copy the template to create a new docx file 
File.Copy(wordTemplateFilePath, wordPrintFilePath, true); 

// Crack open the package 
using (Package packWordPrint = Package.Open(wordPrintFilePath, FileMode.Open, FileAccess.ReadWrite)) 
{ 

    // Retrieve the document.xml part of the new docx file 
    PackagePart part = packWordPrint.GetPart(new Uri("/word/document.xml", UriKind.Relative)); 

    // Create a StreamWriter to be able to write to the stream of the part 
    using (StreamWriter partStream = new StreamWriter(part.GetStream(FileMode.Open, FileAccess.Write))) 
    { 
     // Transform the InfoPath form and save the XML into the stream for the part 
     trans.Transform(this.MainDataSource.CreateNavigator(), null, partStream); 
    } 

    // Write changes to the package 
    packWordPrint.Flush(); 

} 
+0

Merci Foovanadil, pas de fautes d'orthographe, j'ai besoin de la lecture comme c'est le fichier sur lequel je suis en train de transformer. Je définis la variable du formulaire à des fins de nommage, définissez le chemin et le nom de fichier pour le nouveau document à partir des variables, ouvrez le doc xsl à partir des ressources de formulaire que je vais utiliser pour transformer, copiez un doc 2007 J'utilise comme modèle, décompressez-le pour trouver le fichier document.xml qui est le fichier que je vais transformer, et écrivez les changements. Sans autorisation d'écriture, j'obtiens une erreur car je ne peux pas écrire dans le fichier document.xml. Merci cependant, d'autres suggestions mises en œuvre – Richard

0

Je pense que le problème était réellement AV. J'ai toujours une erreur IOException lors de l'utilisation des solutions ci-dessus, les deux que je vais continuer à mettre en œuvre leurs propres droits, mais dès que j'ai mis le répertoire d'écriture dans la liste des exceptions dans le scanner AV, j'ai arrêté les erreurs .

Questions connexes