2012-06-07 13 views
5

में नहीं खुलती है। मैं .NET में एक स्प्रेडशीट जेनरेट करने की कोशिश कर रहा हूं जो मेरे मैनेजर द्वारा कार्यालय से बाहर होने पर मेरे मैनेजर द्वारा खोला जाएगा।.NET में बनाई गई ओपनएक्सएमएल स्प्रेडशीट आईपैड

स्प्रेडशीट एक Windows पीसी पर ठीक खोलता है, लेकिन यह कहते हैं जब आईपैड पर खोलने की कोशिश कर "दस्तावेज़ पढ़ते समय कोई त्रुटि हुई" (ताकि उपयोगी!)

पर सुविधा "तुलना करें" का उपयोग करके एक दस्तावेज़ के साथ ओपनएक्सएमएल एसडीके उत्पादकता उपकरण आईपैड पर खुला है, और नोटपैड में दोषपूर्ण दस्तावेज़ की एक्सएमएल फाइलों के कुछ मैन्युअल संपादन करके मैंने इसे xl/_rels/workbook.xml.rels फ़ाइल में संकुचित कर दिया है। कार्यपुस्तिका में भागों के रिश्तों को स्टोर करता है।

इस कोड और संदर्भ

WorkbookPart workbookPart1 = document.AddWorkbookPart(); 

    WorkbookStylesPart workbookStylesPart1 = workbookPart1.AddNewPart<WorkbookStylesPart>("rId3"); 
    ThemePart themePart1 = workbookPart1.AddNewPart<ThemePart>("rId2"); 
    WorksheetPart worksheetPart1 = workbookPart1.AddNewPart<WorksheetPart>("rId1"); 

मेरे कोड निम्न उत्पादन है, जो आईपैड पर नहीं खुलता उत्पन्न करता है मैं WorkbookPart उत्पन्न करने के लिए उपयोग कर रहा हूँ है।

 <?xml version="1.0" encoding="utf-8" ?> 
     <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> 
      <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="/xl/styles.xml" Id="rId3" /> 
      <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="/xl/theme/theme.xml" Id="rId2" /> 
      <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="/xl/worksheets/sheet.xml" Id="rId1" /> 
     </Relationships> 

अगर मैं बदल लक्ष्य का मूल्य एक रिश्तेदार संदर्भ पथ का उपयोग करने के लिए, निम्न उत्पादन दे रही है विशेषताओं, तो यह आईपैड पर खुला है।

 <?xml version="1.0" encoding="utf-8" ?> 
     <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> 
      <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml" Id="rId3" /> 
      <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme.xml" Id="rId2" /> 
      <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet.xml" Id="rId1" /> 
     </Relationships> 

तो सवाल यह है:
मैं कैसे संबंधित पथ के साथ इतना है कि यह एक्सएमएल के दूसरे संस्करण आउटपुट मेरी नेट कोड बदल सकता हूँ,।

सभी मदद आभारी रूप से प्राप्त हुई!

+0

यह प्रोग्रामिंग प्रश्न की तुलना में "उपयोग कैसे करें" प्रश्न की तरह लगता है, लेकिन वैसे भी, आईपैड पर कौन सा एप्लिकेशन स्प्रेडशीट खोलने का प्रयास कर रहा है? –

+0

क्षमा करें मुझे समझ में नहीं आता कि आप "कैसे उपयोग करें" बनाम प्रोग्रामिंग के बारे में क्या मतलब है लेकिन मुझे जवाब देने के लिए धन्यवाद। मैं सिर्फ इसे आईपैड पर सीधे मेल ऐप से खोलने के लिए ईमेल कर रहा हूं। – Jen

+0

मुझे एक ही समस्या है, लेकिन दस्तावेज़ में कोई संबंध फ़ाइल नहीं है, न ही कोई लक्ष्य विशेषता कहीं भी! – simbolo

उत्तर

0

आप एक बार यह बनाया OpenXML स्प्रेडशीट को मान्य करने की कोशिश कर सकते:

using System; 
using System.Collections.Generic; 
using DocumentFormat.OpenXml.Packaging; 
using DocumentFormat.OpenXml.Validation; 

using (OpenXmlPackage document = SpreadsheetDocument.Open(spreadsheetPathToValidate, false)) 
{ 
    var validator = new OpenXmlValidator(); 
    IEnumerable<ValidationErrorInfo> errors = validator.Validate(document); 
    foreach (ValidationErrorInfo info in errors) 
    { 
     try 
     { 
      Console.WriteLine("Validation information: {0} {1} in {2} part (path {3}): {4}", 
         info.ErrorType, 
         info.Node.GetType().Name, 
         info.Part.Uri, 
         info.Path.XPath, 
         info.Description); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Validation failed: {0}", ex); 
     } 
    } 
} 

आशा है कि मदद करता है,

+0

हालांकि यह सफलतापूर्वक मान्य करता है। अगर मैं एसडीके उत्पादकता उपकरण में सत्यापन उपकरण का उपयोग करता हूं तो यह भी सफलतापूर्वक मान्य करता है। इसके अलावा, मुझे वास्तव में इसे बदलने के लिए एक विधि की आवश्यकता है - मैं कोड में रिश्ते के लिए यूआरआई क्षेत्र देख सकता हूं लेकिन इसे केवल पढ़ा जाता है। – Jen

2

एक PDF भेजने का Comradsky का जवाब एक अच्छा विचार है, लेकिन इस मामले में किसी को भी करने में सक्षम होने की जरूरत है इसे हल करें, मैं एक समाधान के साथ आया हूँ। मुझे पता है कि यह एक भयानक हैक है लेकिन यह काम करता है और मैंने इसे "कानूनी रूप से" करने का कोई तरीका नहीं ढूंढने का प्रयास करने में कई घंटे बिताए हैं।

इसमें .rels फ़ाइल खोलना और दस्तावेज़ बंद होने के बाद फ़ाइल के भीतर सीधे XML को संपादित करना शामिल है।

public static void MakeRelativePaths(string filepath) 
    { 
     // Get the namespace strings 
     const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; 
     const string relationshipSchema = "http://schemas.openxmlformats.org/package/2006/relationships"; 

     string documentUri = null; 
     string documentDirectory = null; 
     string documentName = null; 

     Uri relDocUri = null; 

     XName targetAttributeName = null; 
     string targetValue = null; 

     // Open the package 
     using (Package xlPackage = Package.Open(filepath, FileMode.Open, FileAccess.ReadWrite)) 
     { 
      // Get the directory and filename of the main document part (e.g. /xl/workbook.xml). 
      foreach (System.IO.Packaging.PackageRelationship relationship in xlPackage.GetRelationshipsByType(documentRelationshipType)) 
      { 
       documentUri = relationship.TargetUri.ToString(); 

       documentName = System.IO.Path.GetFileName(documentUri); 
       documentDirectory = documentUri.Substring(0, documentUri.Length - documentName.Length); 

       // There should only be document part in the package, but break out anyway. 
       break; 
      } 

      // Load the relationship document 
      relDocUri = new Uri(documentDirectory + "_rels/" + documentName + ".rels", UriKind.Relative); 
      XDocument relDoc = XDocument.Load(xlPackage.GetPart(relDocUri).GetStream()); 

      // Loop through all of the relationship nodes 
      targetAttributeName = XName.Get("Target"); 
      foreach (XElement relNode in relDoc.Elements(XName.Get("Relationships", relationshipSchema)).Elements(XName.Get("Relationship", relationshipSchema))) 
      { 
       // Edit the value of the Target attribute 
       targetValue = relNode.Attribute(targetAttributeName).Value; 

       if (targetValue.StartsWith(documentDirectory)) 
        targetValue = targetValue.Substring(documentDirectory.Length); 

       relNode.Attribute(targetAttributeName).Value = targetValue; 
      } 

      // Save the document 
      relDoc.Save(xlPackage.GetPart(relDocUri).GetStream()); 
     } 
    } 
+0

मुझे एक ही समस्या है - और मैंने इसे कार्यान्वित करने का प्रयास किया है, लेकिन मैं एक स्ट्रीम के भीतर दस्तावेज़ का उपयोग कर रहा हूं, आईओ नहीं। कोई भाग्य इसे जाने के लिए नहीं मिल रहा है। आपका कोड चलता है, और मैं निकाले गए फ़ाइलों की तुलना करने के बाद इसे काम करने की उम्मीद करता हूं। यदि आप मदद कर सकते हैं, तो इसकी सराहना की जाएगी। – JonK

1

मैं थोड़ी देर के लिए इस तरह की समस्या के साथ भी संघर्ष कर रहा हूं। मैं अंततः एक समाधान के साथ आया जो काम करता है। इस कोड को मैं समस्या को ठीक करने

 // Add a new worksheet part to the workbook. 
     WorksheetPart newWorksheetPart = _document.WorkbookPart.AddNewPart<WorksheetPart>(); 
     newWorksheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(new SheetData()); 

     Sheets sheets = _document.WorkbookPart.Workbook.GetFirstChild<Sheets>(); 
     string relationshipId = _document.WorkbookPart.GetIdOfPart(newWorksheetPart); 

     //This bit is required for iPad to be able to read the sheets inside the xlsx file. The file will still work fine in Excel 
     string relationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"; 
     _document.Package.GetPart(_document.WorkbookPart.Uri).CreateRelationship(new Uri(newWorksheetPart.Uri.OriginalString.Replace("/xl/", String.Empty).Trim(), UriKind.Relative), TargetMode.Internal, relationshipType); 
     _document.Package.GetPart(_document.WorkbookPart.Uri).DeleteRelationship(relationshipId); 
     PackageRelationshipCollection sheetRelationships = _document.Package.GetPart(_document.WorkbookPart.Uri).GetRelationshipsByType(relationshipType); 

     relationshipId = sheetRelationships.Where(f => f.TargetUri.OriginalString == newWorksheetPart.Uri.OriginalString.Replace("/xl/", String.Empty).Trim()).Single().Id; 


     // Get a unique ID for the new sheet. 
     uint sheetId = 1; 
     if (sheets.Elements<Sheet>().Count() > 0) 
      sheetId = sheets.Elements<Sheet>().Max(s => s.SheetId.Value) + 1; 

     // Append the new worksheet and associate it with the workbook. 
     Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = sheetName }; 
     sheets.Append(sheet); 

     _worksheets.Add(new Worksheet(newWorksheetPart.Worksheet, sheetId)); 

_document और _worksheets लिखा है, मेरे समाधान वर्ग में निजी चर हैं।

+0

मेरे लिए काम नहीं किया :( – Renan

+0

यह काम कर रहा है! अंत में! (वाई) –

5

मैंने इस पर शोध करने में काफी समय बिताया है और सोचा कि मैं अपने परिणाम साझा करूंगा। ऐसा लगता है कि ओपनएक्सएमएल दो चीजें कर रहा है। 1. content_types.xml फ़ाइल में कार्यपुस्तिका 2 के लिए एक प्रविष्टि गुम है। Xl/_rels/workbook.xml.rels फ़ाइल पूरी तरह से सापेक्ष पथ का उपयोग कर रही है।

एक्सेल स्वयं फ़ाइल ठीक खोलता है लेकिन मैंने आईपैड पर विभिन्न ऐप्स की कोशिश की है और वे सभी असफल हो गए हैं। इसलिए मुझे निम्नलिखित कोड का उपयोग करके फ़ाइलों को मैन्युअल रूप से ठीक करना पड़ा है।यह मानता है कि फ़ाइल की पूरी सामग्री को स्ट्रीम के रूप में पास किया गया है और इसे खोलने और छेड़छाड़ करने के लिए डॉटनेटजिप का उपयोग करता है। उम्मीद है कि यह कोड दूसरों की मदद करता है!

private Stream ApplyOpenXmlFix(Stream input) 
    { 
     const string RELS_FILE = @"xl/_rels/workbook.xml.rels"; 
     const string RELATIONSHIP_ELEMENT = "Relationship"; 
     const string CONTENT_TYPE_FILE = @"[Content_Types].xml"; 
     const string XL_WORKBOOK_XML = "/xl/workbook.xml"; 
     const string TARGET_ATTRIBUTE = "Target"; 
     const string SUPERFLUOUS_PATH = "/xl/"; 
     const string OVERRIDE_ELEMENT = "Override"; 
     const string PARTNAME_ATTRIBUTE = "PartName"; 
     const string CONTENTTYPE_ATTRIBUTE = "ContentType"; 
     const string CONTENTTYPE_VALUE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"; 

     XNamespace contentTypesNamespace = "http://schemas.openxmlformats.org/package/2006/content-types"; 
     XNamespace relsNamespace = "http://schemas.openxmlformats.org/package/2006/relationships"; 
     XDocument xlDocument; 
     MemoryStream memWriter; 

     try 
     { 
      input.Seek(0, SeekOrigin.Begin); 
      ZipFile zip = ZipFile.Read(input); 

      //First we fix the workbook relations file 
      var workbookRelations = zip.Entries.Where(e => e.FileName == RELS_FILE).Single(); 
      xlDocument = XDocument.Load(workbookRelations.OpenReader()); 

      //Remove the /xl/ relative path from all target attributes 
      foreach (var relationship in xlDocument.Root.Elements(relsNamespace + RELATIONSHIP_ELEMENT)) 
      { 
       var target = relationship.Attribute(TARGET_ATTRIBUTE); 

       if (target != null && target.Value.StartsWith(SUPERFLUOUS_PATH)) 
       { 
        target.Value = target.Value.Substring(SUPERFLUOUS_PATH.Length); 
       } 
      } 

      //Replace the content in the source zip file 
      memWriter = new MemoryStream(); 
      xlDocument.Save(memWriter, SaveOptions.DisableFormatting); 
      memWriter.Seek(0, SeekOrigin.Begin); 
      zip.UpdateEntry(RELS_FILE, memWriter); 

      //Now we fix the content types XML file 
      var contentTypeEntry = zip.Entries.Where(e => e.FileName == CONTENT_TYPE_FILE).Single(); 
      xlDocument = XDocument.Load(contentTypeEntry.OpenReader()); 

      if (!xlDocument.Root.Elements().Any(e => 
       e.Name == contentTypesNamespace + OVERRIDE_ELEMENT && 
       e.Attribute(PARTNAME_ATTRIBUTE) != null && 
       e.Attribute(PARTNAME_ATTRIBUTE).Value == XL_WORKBOOK_XML)) 
      { 
       //Add in the missing element 
       var overrideElement = new XElement(
        contentTypesNamespace + OVERRIDE_ELEMENT, 
        new XAttribute(PARTNAME_ATTRIBUTE, XL_WORKBOOK_XML), 
        new XAttribute(CONTENTTYPE_ATTRIBUTE, CONTENTTYPE_VALUE)); 

       xlDocument.Root.Add(overrideElement); 

       //Replace the content 
       memWriter = new MemoryStream(); 
       xlDocument.Save(memWriter, SaveOptions.DisableFormatting); 
       memWriter.Seek(0, SeekOrigin.Begin); 
       zip.UpdateEntry(CONTENT_TYPE_FILE, memWriter); 
      } 

      Stream output = new MemoryStream(); 

      //Save file 
      zip.Save(output); 

      return output; 
     } 
     catch 
     { 
      //Just in case it fails, return the original document 
      return input; 
     } 
    } 
संबंधित मुद्दे