web-dev-qa-db-fra.com

ouvrir la lecture xml à partir d'un fichier Excel

Je veux implémenter openXml sdk 2.5 dans mon projet. Je fais tout dans ce --- lien

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.IO.Packaging;


static void Main(string[] args)
        {

            String fileName = @"C:\OPENXML\BigData.xlsx";
            // Comment one of the following lines to test the method separately.
            ReadExcelFileDOM(fileName);    // DOM
            //ReadExcelFileSAX(fileName);    // SAX
        }

        // The DOM approach.
        // Note that the code below works only for cells that contain numeric values.
        // 
        static void ReadExcelFileDOM(string fileName)
        {
            using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, false))
            {
                WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
                WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
                SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
                string text;

                int rowCount= sheetData.Elements<Row>().Count();

                foreach (Row r in sheetData.Elements<Row>())
                {
                    foreach (Cell c in r.Elements<Cell>())
                    {
                        text = c.CellValue.Text;
                        Console.Write(text + " ");
                    }
                }
                Console.WriteLine();
                Console.ReadKey();
            }
        }

Mais je ne reçois aucune dispute. Il n'est pas entré dans la boucle. Remarque: j'ai également configuré openXml sdk 2.5 sur mon ordinateur

Et je trouve ci-dessous le code, cela fonctionne pour la valeur numérique.Pour la valeur de chaîne, il écrit 0 1 2 ...

 private static void Main(string[] args)
            {
                var filePath = @"C:/OPENXML/BigData.xlsx";
                using (var document = SpreadsheetDocument.Open(filePath, false))
                {
                    var workbookPart = document.WorkbookPart;
                    var workbook = workbookPart.Workbook;

                    var sheets = workbook.Descendants<Sheet>();
                    foreach (var sheet in sheets)
                    {
                        var worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id);
                        var sharedStringPart = workbookPart.SharedStringTablePart;
                        //var values = sharedStringPart.SharedStringTable.Elements<SharedStringItem>().ToArray();

                        string text;
                        var rows = worksheetPart.Worksheet.Descendants<Row>();
                        foreach (var row in rows)
                        {
                            Console.WriteLine();
                            int count = row.Elements<Cell>().Count();

                            foreach (Cell c in row.Elements<Cell>())
                            {

                                text = c.CellValue.InnerText;

                                Console.Write(text + " ");

                            }
                        }
                    }
                }

                Console.ReadLine();
            }
21
altandogan

Votre approche a semblé fonctionner correctement pour moi - en ce sens qu'elle "est entrée dans la boucle". Néanmoins, vous pouvez également essayer quelque chose comme ceci:

void Main()
{
    string fileName = @"c:\path\to\my\file.xlsx";

    using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fs, false))
        {
            WorkbookPart workbookPart = doc.WorkbookPart;
            SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
            SharedStringTable sst = sstpart.SharedStringTable;

            WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
            Worksheet sheet = worksheetPart.Worksheet;

            var cells = sheet.Descendants<Cell>();
            var rows = sheet.Descendants<Row>();

            Console.WriteLine("Row count = {0}", rows.LongCount());
            Console.WriteLine("Cell count = {0}", cells.LongCount());

            // One way: go through each cell in the sheet
            foreach (Cell cell in cells)
            {
                if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
                {
                    int ssid = int.Parse(cell.CellValue.Text);
                    string str = sst.ChildElements[ssid].InnerText;
                    Console.WriteLine("Shared string {0}: {1}", ssid, str);
                }
                else if (cell.CellValue != null)
                {
                    Console.WriteLine("Cell contents: {0}", cell.CellValue.Text);
                }
             }

             // Or... via each row
             foreach (Row row in rows)
             {
                 foreach (Cell c in row.Elements<Cell>())
                 {
                     if ((c.DataType != null) && (c.DataType ==           CellValues.SharedString))
                     {
                         int ssid = int.Parse(c.CellValue.Text);
                         string str = sst.ChildElements[ssid].InnerText;
                         Console.WriteLine("Shared string {0}: {1}", ssid, str);
                     }
                     else if (c.CellValue != null)
                     {
                         Console.WriteLine("Cell contents: {0}", c.CellValue.Text);
                     }
                 }
             }
         }
     }
 }

J'ai utilisé l'approche filestream pour ouvrir le classeur, car cela vous permet de l'ouvrir avec un accès partagé - afin que vous puissiez ouvrir le classeur dans Excel en même temps. La méthode Spreadsheet.Open (... ne fonctionnera pas si le classeur est ouvert ailleurs.

C'est peut-être pour cela que votre code n'a pas fonctionné.

Notez également l'utilisation de SharedStringTable pour obtenir le texte de la cellule le cas échéant.

EDIT 2018-07-11:

Étant donné que ce message reçoit toujours des votes, je dois également souligner que dans de nombreux cas, il peut être beaucoup plus facile à utiliser ClosedXML pour manipuler/lire/modifier vos classeurs. Les exemples de documentation sont assez conviviaux et le codage est, dans mon expérience limitée, beaucoup plus simple. Sachez simplement qu'il n'implémente pas (encore) toutes les fonctions Excel (par exemple INDEX et MATCH) qui peuvent ou non être un problème. [Non pas que je voudrais de toute façon essayer de gérer INDEX et MATCH dans OpenXML.]

56
shunty

J'ai eu le même problème que le PO et la réponse ci-dessus n'a pas fonctionné pour moi.

Je pense que c'est le problème: lorsque vous créez un document dans Excel (pas par programme), vous avez 3 feuilles par défaut et le WorksheetParts qui contient les données de ligne pour Sheet1 est le dernier élément WorksheetParts, pas le premier.

J'ai compris cela en mettant une montre pour document.WorkbookPart.WorksheetParts dans Visual Studio, en développant les résultats, puis en regardant tous les sous-éléments jusqu'à ce que je trouve un objet SheetData où HasChildren = true.

Essaye ça:

// open the document read-only
SpreadSheetDocument document = SpreadsheetDocument.Open(filePath, false);
SharedStringTable sharedStringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable;
string cellValue = null;

foreach (WorksheetPart worksheetPart in document.WorkbookPart.WorksheetParts)
{
    foreach (SheetData sheetData in worksheetPart.Worksheet.Elements<SheetData>())
    {
        if (sheetData.HasChildren)
        {
            foreach (Row row in sheetData.Elements<Row>())
            {
                foreach (Cell cell in row.Elements<Cell>())
                {
                    cellValue = cell.InnerText;

                    if (cell.DataType == CellValues.SharedString)
                    {
                        Console.WriteLine("cell val: " + sharedStringTable.ElementAt(Int32.Parse(cellValue)).InnerText);
                    }
                    else
                    {
                        Console.WriteLine("cell val: " + cellValue);
                    }
                }
            }
        }
    }
}
document.Close();
10
vik