Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing underlying excel data sheet does not update other worksheets #1684

Open
bkatchmar opened this issue Mar 4, 2024 · 1 comment
Open

Comments

@bkatchmar
Copy link

bkatchmar commented Mar 4, 2024

Describe the bug
I have a power point presentation with charts powered by data in an excel OLE object.

valentineschocolates.pptx

There is a presentation layer and a Data sheet that powers the prettier presentation sheet (there are also custom fonts associated here). Within the presentation, there are two rows of interest:

THE HERSEY CO: $123
MARS INC: $456

I run the below code, primarily if not exclusively using the OpenXML code to open the PPTX, get inside the Excel object, update the data for these two rows, save and close. However, when I re-open the file again, the object does not appear updated but when I double click on the object, then and only then, does the data "snap" to the correct values.

Is it possible I am not setting an "AutoUpdate" flag correctly or not calling something to have this updated before a user needs to open the file and double click?

NuGet Packages Used (some of these are not used in the code example)

  <ItemGroup>
    <PackageReference Include="Aspose.Cells" Version="24.2.0" />
    <PackageReference Include="Aspose.Slides.NET" Version="24.1.0" />
    <PackageReference Include="DocumentFormat.OpenXml" Version="3.0.1" />
    <PackageReference Include="Microsoft.AnalysisServices.AdomdClient.NetCore.retail.amd64" Version="19.76.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageReference Include="SendGrid" Version="9.29.1" />
  </ItemGroup>

Code

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Spreadsheet;
using Newtonsoft.Json;
using System.Text;

TestAsposeDataRefresh();

static void TestAsposeDataRefresh()
{
    List<string> queryKeys = new() { "SLIDE328_OBJECT 6" };
    string directory = @"[Directory Omitted]\valentineschocolates.pptx";
    using FileStream ReportStream = File.Open(directory, FileMode.Open, FileAccess.ReadWrite);

    // First open the document using OpenXML to change the data (Aspose ignore this)
    PresentationDocument presentationDocument = PresentationDocument.Open(ReportStream, true);
    PresentationPart? presentationPart = presentationDocument.PresentationPart;

    if (presentationPart != null)
    {
        SlideIdList? slideList = presentationPart.Presentation.SlideIdList;

        if (slideList != null)
        {
            OpenXmlElementList slideIDs = slideList.ChildElements;

            for (int i = 0; i <= slideIDs.Count - 1; i++)
            {
                SlideId? slideId = slideIDs[i] as SlideId;
                StringValue? slidePartRelationshipID = slideId.RelationshipId;
                SlidePart slidePart = (SlidePart)presentationPart.GetPartById(slidePartRelationshipID);
                int slideID = Convert.ToInt32(slideId.Id.ToString());

                foreach (GraphicFrame gf in slidePart.Slide.Descendants<GraphicFrame>())
                {
                    foreach (NonVisualDrawingProperties nvdp in gf.Descendants<NonVisualDrawingProperties>())
                    {
                        if (gf.Graphic.GraphicData.Uri.ToString().Contains("ole"))
                        {
                            string shapeName = nvdp.Name.ToString().ToUpper();
                            string queryKey = string.Concat("SLIDE", slideID.ToString(), "_", shapeName);

                            foreach (DocumentFormat.OpenXml.Presentation.OleObject ole in gf.Descendants<DocumentFormat.OpenXml.Presentation.OleObject>())
                            {
                                if (ole != null)
                                {
                                    if (string.Compare(slidePart.GetPartById(ole.Id.Value).GetType().Name, "EmbeddedPackagePart") == 0)
                                    {
                                        EmbeddedPackagePart epp = (EmbeddedPackagePart)slidePart.GetPartById(ole.Id.Value);
                                        if (queryKeys.Contains(queryKey))
                                        {
                                            using Stream embeddedPackagePartStream = epp.GetStream();
                                            using SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(embeddedPackagePartStream, true);
                                            UpdateChartData(spreadsheetDocument);
                                            spreadsheetDocument.Save();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        presentationDocument.Save();
    }

    Console.WriteLine("Done");
}

static void ExperimentWithOpenXML()
{

    Dictionary<string, string> sheetNames = new();
    Dictionary<string, string> newValues = new()
    {
        { "A1", "G" },
        { "A2", "H" },
        { "A3", "I" },
        { "B1", "7" },
        { "B2", "8" },
        { "B3", "9" }
    };
    string directory = @"C:\Users\brian\OneDrive\Documents\ghirardelli\Book1.xlsx";
    Console.WriteLine($"Opening File: {directory}");
    Console.WriteLine("");
    using FileStream reportStream = File.Open(directory, FileMode.Open, FileAccess.ReadWrite);

    // Create a spreadsheet document by supplying the file name.  
    SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(reportStream, true);
    WorkbookPart? wbp = spreadsheetDocument.WorkbookPart;

    // Read details of the workbook
    if (wbp != null)
    {
        foreach (Sheet sheet in wbp.Workbook.Descendants<Sheet>())
        {
            StringValue? sheetId = sheet.Id;
            StringValue? sheetName = sheet.Name;

            if (sheetId != null && sheetId.HasValue && sheetName != null && sheetName.HasValue)
            {
                sheetNames.Add(sheetId, sheetName);
            }
        }

        // List the sheet names
        foreach (KeyValuePair<string, string> sheet in sheetNames)
        {
            Console.WriteLine($"Sheet Key: {sheet.Key}; Sheet Name: {sheet.Value}");
        }
        Console.WriteLine("");

        // Going through the Worksheets
        foreach (WorksheetPart sheet in wbp.WorksheetParts)
        {
            DocumentFormat.OpenXml.Spreadsheet.Worksheet worksheet = sheet.Worksheet;
            SheetData? sheetData = worksheet.GetFirstChild<SheetData>();

            if (sheetData != null)
            {
                DocumentFormat.OpenXml.Spreadsheet.Row[] rows = sheetData.Elements<DocumentFormat.OpenXml.Spreadsheet.Row>().ToArray();

                for (int x = 0; x < rows.Count(); x++)
                {
                    foreach (DocumentFormat.OpenXml.Spreadsheet.Cell c in rows[x].Elements<DocumentFormat.OpenXml.Spreadsheet.Cell>().ToArray())
                    {
                        if (c.DataType != null && c.DataType == CellValues.SharedString)
                        {
                            int stringId = Convert.ToInt32(c.InnerText);
                            SharedStringTablePart? tablePart = wbp.SharedStringTablePart;
                            if (tablePart != null)
                            {
                                string cellValue = tablePart.SharedStringTable.Elements<SharedStringItem>().ElementAt(stringId).InnerText;
                                Console.WriteLine($"Cell: {c.CellReference}; Value: {cellValue}; Data Type: {c.DataType}");
                            }

                            if (newValues.ContainsKey(c.CellReference))
                            {
                                DocumentFormat.OpenXml.Spreadsheet.CellValue newValue = new(newValues[c.CellReference]);
                                c.CellValue = newValue;
                            }
                        }
                        else
                        {
                            Console.WriteLine($"Cell: {c.CellReference}; Value: {c.CellValue.InnerText}; Data Type: {c.DataType}");

                            if (newValues.ContainsKey(c.CellReference))
                            {
                                DocumentFormat.OpenXml.Spreadsheet.CellValue newValue = new(int.Parse(newValues[c.CellReference]));
                                c.CellValue = newValue;
                            }
                        }
                    }
                }
            }
        }
    }

    spreadsheetDocument.Save();
}

static void TestAsposeDataRefresh2()
{
    Console.WriteLine("TestAsposeDataRefresh2");

    string jsonObjectArrayData = "[[\"Product\",\"Time Period\",\"Geography\",\"Dollar Sales\",\"Dollar Sales Year Ago\",\"Unit Sales\",\"Unit Sales Year Ago\"],[\"VALENTINE\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",1017922.0,848299.0,274256.0,264593.0],[\"THE HERSHEY CO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",453137.0,358935.0,124223.0,94165.0],[\"MARS INC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",163497.0,165286.0,38117.0,45832.0],[\"RUSSELL STOVER CHOCOLATES, LLC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",162167.0,142333.0,41123.0,55579.0],[\"LINDT\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",102415.0,52291.0,17452.0,12425.0],[\"GHIRARDELLI CHOCOLATE CO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",32874.0,39488.0,4356.0,5766.0],[\"R M PALMER CO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",26549.0,19967.0,18800.0,17168.0],[\"FRANKFORD CANDY LLC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",22573.0,15824.0,11906.0,15862.0],[\"FERRERO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",17172.0,13933.0,7028.0,6784.0],[\"GODIVA CHOCOLATIER\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",17147.0,27946.0,2337.0,3901.0],[\"FERRARA CANDY CO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",15645.0,5790.0,3138.0,1192.0],[\"TOOTSIE ROLL INDS INC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",4312.0,3446.0,3510.0,3454.0],[\"R L ALBERT & SON INC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",3286.0,3051.0,2266.0,2459.0],[\"BK Broiler INC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",3137.0,8675.0,3096.0,666.0]]";
    List<object[]> modifiedDataList = JsonConvert.DeserializeObject<List<object[]>>(jsonObjectArrayData);

    List<string> queryKeys = new() { "SLIDE328_OBJECT 6" };
    string directory = @"[Directory Omitted]\ghirardelli.pptx";

    Dictionary<string, string> newValues = new()
    {
        { "D3", "453137" }
    };

    using FileStream ReportStream = File.Open(directory, FileMode.Open, FileAccess.ReadWrite);

    // First open the document using OpenXML to change the data (Aspose ignore this)
    bool openXmlPassed = false;
    PresentationDocument presentationDocument = PresentationDocument.Open(ReportStream, true);
    PresentationPart? presentationPart = presentationDocument.PresentationPart;

    if (presentationPart != null)
    {
        SlideIdList? slideList = presentationPart.Presentation.SlideIdList;

        if (slideList != null)
        {
            OpenXmlElementList slideIDs = slideList.ChildElements;

            for (int i = 0; i <= slideIDs.Count - 1; i++)
            {
                SlideId? slideId = slideIDs[i] as SlideId;
                StringValue? slidePartRelationshipID = slideId.RelationshipId;
                SlidePart slidePart = (SlidePart)presentationPart.GetPartById(slidePartRelationshipID);
                int slideID = Convert.ToInt32(slideId.Id.ToString());

                foreach (GraphicFrame gf in slidePart.Slide.Descendants<GraphicFrame>())
                {
                    foreach (NonVisualDrawingProperties nvdp in gf.Descendants<NonVisualDrawingProperties>())
                    {
                        if (gf.Graphic.GraphicData.Uri.ToString().Contains("ole"))
                        {
                            string shapeName = nvdp.Name.ToString().ToUpper();
                            string queryKey = string.Concat("SLIDE", slideID.ToString(), "_", shapeName);

                            foreach (DocumentFormat.OpenXml.Presentation.OleObject ole in gf.Descendants<DocumentFormat.OpenXml.Presentation.OleObject>())
                            {
                                if (ole != null)
                                {
                                    if (string.Compare(slidePart.GetPartById(ole.Id.Value).GetType().Name, "EmbeddedPackagePart") == 0)
                                    {
                                        EmbeddedPackagePart epp = (EmbeddedPackagePart)slidePart.GetPartById(ole.Id.Value);
                                        if (queryKeys.Contains(queryKey))
                                        {
                                            using Stream embeddedPackagePartStream = epp.GetStream();
                                            using SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(embeddedPackagePartStream, true);
                                            WorkbookPart? wbp = spreadsheetDocument.WorkbookPart;

                                            Dictionary<string, string> sheetNames = new();
                                            foreach (Sheet sheet in wbp.Workbook.Descendants<Sheet>())
                                            {
                                                StringValue? sheetId = sheet.Id;
                                                StringValue? sheetName = sheet.Name;

                                                if (sheetId != null && sheetId.HasValue && sheetName != null && sheetName.HasValue)
                                                {
                                                    sheetNames.Add(sheetId, sheetName);
                                                }
                                            }

                                            // List the sheet names
                                            foreach (KeyValuePair<string, string> sheet in sheetNames)
                                            {
                                                Console.WriteLine($"Query Key: {queryKey}; Sheet Key: {sheet.Key}; Sheet Name: {sheet.Value}");
                                            }
                                            Console.WriteLine("");

                                            // Going through the Worksheets
                                            foreach (WorksheetPart sheet in wbp.WorksheetParts)
                                            {
                                                DocumentFormat.OpenXml.Spreadsheet.Worksheet worksheet = sheet.Worksheet;
                                                SheetData? sheetData = worksheet.GetFirstChild<SheetData>();

                                                if (sheetData != null)
                                                {
                                                    DocumentFormat.OpenXml.Spreadsheet.Row[] rows = sheetData.Elements<DocumentFormat.OpenXml.Spreadsheet.Row>().ToArray();

                                                    for (int x = 0; x < rows.Count(); x++)
                                                    {
                                                        foreach (DocumentFormat.OpenXml.Spreadsheet.Cell c in rows[x].Elements<DocumentFormat.OpenXml.Spreadsheet.Cell>().ToArray())
                                                        {
                                                            if (c.CellValue != null)
                                                            {
                                                                if (c.DataType != null && c.DataType == CellValues.SharedString)
                                                                {
                                                                    int stringId = Convert.ToInt32(c.InnerText);
                                                                    SharedStringTablePart? tablePart = wbp.SharedStringTablePart;
                                                                    if (tablePart != null)
                                                                    {
                                                                        string cellValue = tablePart.SharedStringTable.Elements<SharedStringItem>().ElementAt(stringId).InnerText;
                                                                        if (c.CellReference == "D3")
                                                                        {
                                                                            Console.WriteLine($"Cell: {c.CellReference}; Value: {cellValue}; Data Type: {c.DataType}");
                                                                        }
                                                                    }

                                                                    if (newValues.ContainsKey(c.CellReference))
                                                                    {
                                                                        DocumentFormat.OpenXml.Spreadsheet.CellValue newValue = new(newValues[c.CellReference]);
                                                                        c.CellValue = newValue;
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    if (c.CellReference == "D3")
                                                                    {
                                                                        Console.WriteLine($"Cell: {c.CellReference}; Value: {c.CellValue.InnerText}; Data Type: {c.DataType}");
                                                                    }

                                                                    if (newValues.ContainsKey(c.CellReference))
                                                                    {
                                                                        DocumentFormat.OpenXml.Spreadsheet.CellValue newValue = new(int.Parse(newValues[c.CellReference]));
                                                                        c.CellValue = newValue;
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }

                                                    worksheet.Save();
                                                }
                                            }

                                            spreadsheetDocument.Save();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        presentationDocument.Save();
    }
}

#region OpenXML Private Helper Classes (Strictly to update the excel object)
static void UpdateChartData(SpreadsheetDocument sd)
{
    WorkbookPart wbp = sd.WorkbookPart;
    Dictionary<string, string> sheetNames = new Dictionary<string, string>();
    string jsonObjectArrayData = "[[\"Product\",\"Time Period\",\"Geography\",\"Dollar Sales\",\"Dollar Sales Year Ago\",\"Unit Sales\",\"Unit Sales Year Ago\"],[\"VALENTINE\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",1017922.0,848299.0,274256.0,264593.0],[\"THE HERSHEY CO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",453137.0,358935.0,124223.0,94165.0],[\"MARS INC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",163497.0,165286.0,38117.0,45832.0],[\"RUSSELL STOVER CHOCOLATES, LLC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",162167.0,142333.0,41123.0,55579.0],[\"LINDT\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",102415.0,52291.0,17452.0,12425.0],[\"GHIRARDELLI CHOCOLATE CO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",32874.0,39488.0,4356.0,5766.0],[\"R M PALMER CO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",26549.0,19967.0,18800.0,17168.0],[\"FRANKFORD CANDY LLC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",22573.0,15824.0,11906.0,15862.0],[\"FERRERO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",17172.0,13933.0,7028.0,6784.0],[\"GODIVA CHOCOLATIER\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",17147.0,27946.0,2337.0,3901.0],[\"FERRARA CANDY CO\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",15645.0,5790.0,3138.0,1192.0],[\"TOOTSIE ROLL INDS INC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",4312.0,3446.0,3510.0,3454.0],[\"R L ALBERT & SON INC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",3286.0,3051.0,2266.0,2459.0],[\"BK Broiler INC\",\"Vday 2023 12WE 02-19-2023\",\"Weis Corp\",3137.0,8675.0,3096.0,2459.0]]";
    List<object[]> modifiedDataList = JsonConvert.DeserializeObject<List<object[]>>(jsonObjectArrayData);

    string sNewRange = CalcExcelTableRange(modifiedDataList);
    string dataSheetName = "Sheet1", sheetID = string.Empty, sheetName = string.Empty;
    DocumentFormat.OpenXml.Spreadsheet.Worksheet worksheet = null;

    foreach (Sheet sheet in wbp.Workbook.Descendants<Sheet>())
    {
        sheetNames.Add(sheet.Id, sheet.Name);

        if (string.Compare(sheet.Name, "Data", true) == 0)
        {
            dataSheetName = "Data";
        }
    }

    wbp.Workbook.CalculationProperties.ForceFullCalculation = true;
    wbp.Workbook.CalculationProperties.FullCalculationOnLoad = true;

    foreach (WorksheetPart sheet in wbp.WorksheetParts)
    {
        sheetID = wbp.GetIdOfPart(sheet);
        worksheet = sheet.Worksheet;
        sheetName = sheetNames[sheetID];

        if (string.Compare(sheetName, dataSheetName, true) == 0 || string.Compare(sheetName, "Chart", true) == 0)
        {
            if (!sheet.PivotTableParts.Any() && !sheet.TableDefinitionParts.Any())
            {
                string sOldRange = "A1:G14";
                ClearSheet(worksheet, sOldRange);
                WriteSheetDataOffset(worksheet, modifiedDataList, sOldRange.Substring(0, sNewRange.IndexOf(':')));

                // We need to make sure the new sheet's reference saves properly
                worksheet.SheetDimension.Reference = sNewRange;
                break;
            }
        }
    }
}
static string CalcExcelTableRange(List<object[]> data)
{
    string sRange = "A1:" + GenerateRange(data[0].Length, data.Count);

    return sRange;
}
static string GenerateRange(int endColumn, int endRow)
{
    StringBuilder sb = new StringBuilder();
    int root = 0, suffix = 0;
    char left = default(char), right = default(char);

    root = endColumn / 26;
    suffix = endColumn % 26;

    if (root > 0)
    {
        if (root == 1)
        {
            if (suffix > 0)
            {
                left = Convert.ToChar(root + 64);
                right = Convert.ToChar(suffix + 64);
                sb.Append(left);
                sb.Append(right);
            }
            else
            {
                sb.Append(Convert.ToChar(endColumn + 64));
            }
        }
        else
        {
            if (suffix > 0)
            {
                left = Convert.ToChar(root + 64);
                right = Convert.ToChar(suffix + 64);
            }
            else
            {
                left = Convert.ToChar(root - 1 + 64);
                right = Convert.ToChar(90);
            }

            sb.Append(left);
            sb.Append(right);
        }
    }
    else
    {
        sb.Append(Convert.ToChar(endColumn + 64));
    }

    sb.Append(endRow.ToString());

    return sb.ToString();
}
static void ClearSheet(DocumentFormat.OpenXml.Spreadsheet.Worksheet worksheet, string range = "")
{
    SheetData sheetData = worksheet.GetFirstChild<SheetData>();
    string startCell = string.Empty;
    string startCol = string.Empty;
    string currCol = string.Empty;
    string endCol = string.Empty;
    string endCell = string.Empty;
    DocumentFormat.OpenXml.Spreadsheet.Row[] rows = sheetData.Elements<DocumentFormat.OpenXml.Spreadsheet.Row>().ToArray();
    string[] srange = null;

    //bug236
    range = range.Replace("$", String.Empty);

    if (range != string.Empty)
    {
        srange = range.Split(':');

        if (range.Contains(':'))
        {
            startCell = srange[0];
            endCell = srange[1];
        }
        else
        {
            startCell = srange[0];
            endCell = srange[0];
        }

        for (int x = 0; x < rows.Count(); x++)
        {
            foreach (DocumentFormat.OpenXml.Spreadsheet.Cell c in rows[x].Elements<DocumentFormat.OpenXml.Spreadsheet.Cell>().ToArray())
            {
                if (Compare(c.CellReference, startCell) >= 0 && Compare(c.CellReference, endCell) <= 0)
                {
                    if (c.CellValue != null)
                    {
                        c.CellValue.Remove();
                    }
                    c.CellValue = null;
                }
            }
        }
    }
    worksheet.Save();
}
static int Compare(string x, string y)
{
    int returnValue = -1;
    string startX = string.Empty, startY = string.Empty, colX = string.Empty,
        colY = string.Empty, rowX = string.Empty, rowY = string.Empty;
    int rowXNumeric = -1, rowYNumeric = -1;

    if (string.Equals(x, y))
    {
        returnValue = 0;
    }
    else
    {

        if ((x.IndexOf(":") < 0) || (y.IndexOf(":") < 0))
        {
            startX = x;
            startY = y;
        }
        else
        {
            startX = x.Substring(0, x.IndexOf(":"));
            startY = y.Substring(0, y.IndexOf(":"));
        }

        foreach (char c in startX)
        {
            if (!char.IsNumber(c))
            {
                colX += c;
            }
            else
            {
                rowX += c;
            }
        }

        foreach (char c in startY)
        {
            if (!char.IsNumber(c))
            {
                colY += c;
            }
            else
            {
                rowY += c;
            }
        }

        if (colX.Length != colY.Length)
        {
            returnValue = colX.Length - colY.Length;
        }
        else
        {
            returnValue = string.Compare(colX, colY, true);

            //bug244 only geography showed since cleared wrong area
            if (returnValue >= 0)
            {
                rowXNumeric = int.Parse(rowX);
                rowYNumeric = int.Parse(rowY);
                returnValue = rowXNumeric - rowYNumeric >= 0 ? 1 : -1;
            }
        }
    }

    return returnValue;
}
static void WriteSheetDataOffset(DocumentFormat.OpenXml.Spreadsheet.Worksheet worksheet, List<object[]> data, string startPosition)
{
    SheetData sheetData = worksheet.WorksheetPart.Worksheet.GetFirstChild<SheetData>();

    List<DocumentFormat.OpenXml.Spreadsheet.Cell> existingCells = new List<DocumentFormat.OpenXml.Spreadsheet.Cell>();
    string cellCol = string.Empty;
    DocumentFormat.OpenXml.Spreadsheet.Row prevRow = null;
    DocumentFormat.OpenXml.Spreadsheet.Row rowBuilder = null;
    DocumentFormat.OpenXml.Spreadsheet.Cell cell = null;
    DocumentFormat.OpenXml.Spreadsheet.Cell nextCell = null;
    object val = null;
    int startColumn = 0, startRow = 0;
    StringBuilder columnSB = new(), rowSB = new();

    //bug236
    startPosition = startPosition.Replace("$", String.Empty);

    foreach (char c in startPosition)
    {
        if (char.IsNumber(c))
        {
            rowSB.Append(c);
        }
        else
        {
            columnSB.Append(c);
        }
    }

    startRow = Convert.ToInt32(rowSB.ToString().Trim());
    startColumn = ConvertColumnStringToNumeric(columnSB.ToString());

    for (int i = 0; i <= data.Count - 1; i++)
    {
        if (sheetData.Elements<DocumentFormat.OpenXml.Spreadsheet.Row>().Count(r => r.RowIndex == i + startRow) != 0)
        {
            rowBuilder = sheetData.Elements<DocumentFormat.OpenXml.Spreadsheet.Row>().First(r => r.RowIndex == i + startRow);
        }
        else
        {
            if (rowBuilder != null)
            {
                prevRow = rowBuilder;
            }

            rowBuilder = new DocumentFormat.OpenXml.Spreadsheet.Row { RowIndex = (uint)(i + startRow) };

            if (prevRow != null)
            {
                sheetData.InsertAfter(rowBuilder, prevRow); // Needs to be an insert after prior row
            }
            else
            {
                sheetData.Append(rowBuilder);
            }
        }

        existingCells = rowBuilder.Elements<DocumentFormat.OpenXml.Spreadsheet.Cell>().ToList();

        for (int j = 0; j <= data[i].GetUpperBound(0); j++)
        {
            if (existingCells != null && existingCells.Count > 0)
            {
                DocumentFormat.OpenXml.Spreadsheet.Cell existingCell = existingCells.Find(
                    c => string.Compare(c.CellReference, GenerateRange(startColumn + j, startRow + i), true) == 0);

                if (existingCell != null)
                {
                    if (data[i][j] is double || data[i][j] == null || data[i][j] == DBNull.Value)
                    {
                        existingCell.DataType = CellValues.Number;
                        val = data[i].GetValue(j);

                        existingCell.CellValue = val == null ? null : new DocumentFormat.OpenXml.Spreadsheet.CellValue(val.ToString());
                    }
                    else
                    {
                        existingCell.DataType = CellValues.String;
                        existingCell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(data[i].GetValue(j) == null ? string.Empty : data[i].GetValue(j).ToString());
                    }
                }
                else
                {
                    if (data[i][j] is double || data[i][j] == null || data[i][j] == DBNull.Value)
                    {
                        cell = new DocumentFormat.OpenXml.Spreadsheet.Cell
                        {
                            CellReference = GenerateRange(startColumn + j, startRow + i),
                            DataType = CellValues.Number,
                            CellValue = data[i].GetValue(j) == null ? null : new DocumentFormat.OpenXml.Spreadsheet.CellValue(data[i].GetValue(j).ToString()),
                            StyleIndex = 0,
                        };
                    }
                    else
                    {
                        cell = new DocumentFormat.OpenXml.Spreadsheet.Cell
                        {
                            CellReference = GenerateRange(startColumn + j, startRow + i),
                            DataType = CellValues.String,
                            CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(data[i].GetValue(j) == null ? string.Empty : data[i].GetValue(j).ToString()),
                        };
                    }

                    bool insert = false;

                    foreach (DocumentFormat.OpenXml.Spreadsheet.Cell c in existingCells)
                    {
                        if (GetAsciiValueofText(cell.CellReference) < GetAsciiValueofText(c.CellReference))
                        {
                            insert = true;
                            nextCell = c;
                            break;
                        }
                    }

                    if (insert)
                    {
                        rowBuilder.InsertBefore(cell, nextCell);
                    }
                    else
                    {
                        rowBuilder.Append(cell);
                    }
                }
            }
            else
            {
                if (data[i][j] is double || data[i][j] == null || data[i][j] == DBNull.Value)
                {
                    cell = new DocumentFormat.OpenXml.Spreadsheet.Cell
                    {
                        CellReference = GenerateRange(startColumn + j, startRow + i),
                        DataType = CellValues.Number,
                        CellValue = data[i].GetValue(j) == null ? null : new DocumentFormat.OpenXml.Spreadsheet.CellValue(data[i].GetValue(j).ToString()),
                        StyleIndex = 0,
                    };
                }
                else
                {
                    cell = new DocumentFormat.OpenXml.Spreadsheet.Cell
                    {
                        CellReference = GenerateRange(startColumn + j, startRow + i),
                        DataType = CellValues.String,
                        CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(data[i].GetValue(j) == null ? string.Empty : data[i].GetValue(j).ToString()),
                    };
                }
                rowBuilder.Append(cell);
            }
        }
    }

    worksheet.Save();
}
static int ConvertColumnStringToNumeric(string columnString)
{
    int columnValue = 0, power = 0, mantissa = 0, exponent = 0;
    //bug236
    columnString = columnString.Replace("$", String.Empty);

    power = columnString.Length - 1;

    foreach (char c in columnString)
    {
        mantissa = (int)Math.Pow(26.0d, power);
        exponent = c - 64;
        columnValue += mantissa * exponent;
        power--;
    }

    return columnValue;
}
static int GetAsciiValueofText(string text)
{
    int i = 0;
    foreach (char c in text)
    {
        i = i + c;
    }
    return i;
}
#endregion
@twsouthwick
Copy link
Member

Can you please simplify this repro? There's too much going on to identify what the issue is. Make sure you're disposing everything that needs to be (doesn't look like you dispose the presentation). We can't try this out as it requires an input file it seems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants