【问题标题】:open xml excel Insert actual value in the placeholder打开 xml excel 在占位符中插入实际值
【发布时间】:2011-05-09 08:30:49
【问题描述】:

我在 Excel 工作表中有一个包含占位符“$$value”的单元格,问题是我需要使用 Open XML 替换占位符的实际值并将其保存为单独的工作簿。

这是我尝试过的代码...它没有替换实际值,而且我无法保存工作簿。我需要解决这个问题。

WorksheetPart worksheetPart = (WorksheetPart)myWorkbook.WorkbookPart.GetPartById(sheet.Id);

DocumentFormat.OpenXml.Spreadsheet.Worksheet worksheet = worksheetPart.Worksheet;

string _txt1 = "$$value";

if (_txt1.Contains("$$"))

{

     worksheet.InnerText.Replace(_txt1, "test");

}

【问题讨论】:

    标签: c# excel openxml-sdk


    【解决方案1】:

    默认情况下,Excel 将字符串存储在全局(每个工作簿 1 个)SharedStringTablePart 中。因此,这是您需要定位的目标。但是,OpenXML 格式也允许在 WorksheetParts 内嵌入文本。因此,还需要查看完整的解决方案。

    这是一个示例应用程序(带有一些内联 cmets):

    using DocumentFormat.OpenXml.Packaging;
    using x = DocumentFormat.OpenXml.Spreadsheet;
    
    class Program
    {
    private static readonly string placeHolder = "$$value";
    
    static void Main()
    {
        var templatePath = @"C:\Temp\template.xlsx";
        var resultPath = @"C:\Temp\result.xlsx";
        string replacementText = "test";
    
        using (Stream xlsxStream = new MemoryStream())
        {
            // Read template from disk
            using (var fileStream = File.OpenRead(templatePath)) 
                fileStream.CopyTo(xlsxStream);
    
            // Do replacements
            ProcessTemplate(xlsxStream, replacementText);
    
            // Reset stream to beginning
            xlsxStream.Seek(0L, SeekOrigin.Begin);
    
            // Write results back to disk
            using (var resultFile = File.Create(resultPath))
                xlsxStream.CopyTo(resultFile);
        }
    }
    
    private static void ProcessTemplate(Stream template, string replacementText)
    {
        using (var workbook = SpreadsheetDocument.Open(template, true, new OpenSettings { AutoSave = true }))
        {
            // Replace shared strings
            SharedStringTablePart sharedStringsPart = workbook.WorkbookPart.SharedStringTablePart;
            IEnumerable<x.Text> sharedStringTextElements = sharedStringsPart.SharedStringTable.Descendants<x.Text>();
            DoReplace(sharedStringTextElements, replacementText);
    
            // Replace inline strings
            IEnumerable<WorksheetPart> worksheetParts = workbook.GetPartsOfType<WorksheetPart>();
            foreach (var worksheet in worksheetParts)
            {
                var allTextElements = worksheet.Worksheet.Descendants<x.Text>();
                DoReplace(allTextElements, replacementText);
            }
    
        } // AutoSave enabled
    }
    
    private static void DoReplace(IEnumerable<x.Text> textElements, string replacementText)
    {
        foreach (var text in textElements)
        {
            if (text.Text.Contains(placeHolder))
                text.Text = text.Text.Replace(placeHolder, replacementText);
        }
    }
    

    【讨论】:

    • 嗨 ServiceGuy 感谢您的回复...您的代码面临的问题是我无法使用“new OpenSettings {AutoSave = true }”保存它获取“OpenSetting”的参考问题..有没有其他方法可以将工作簿另存为另一个工作簿,将其作为模板....
    • @kart:我更新了示例代码以满足您的要求(加载模板并保存到新文件)。另外,请确保使用 OpenXML SDK 2.0 的 RTM:microsoft.com/downloads/en/…
    • @ServiceGuy:非常感谢您的指导......在调试时,我可以在 DoReplace 函数中找到文本替换,但那些替换的文本没有显示在新创建的 excel 文件中。对我来说,我无法添加 OpenSetting "SpreadsheetDocument.Open(template, true, new OpenSettings { AutoSave = true })" 第三个参数不允许在 "SpreadsheetDocument.Open()" 方法中它只允许两个参数.. .仍然无法替换新创建的文件中的实际数据..它的创建与模板文件相同。
    • @kart:需要使用OpenXml SDK 2的RTM,版本号为2.0.5022。他们添加了自动保存功能,并且该方法重载相对较晚。我很确定您使用的是旧版本,这就是它不适合您的原因,它还可以解释为什么新值不会出现在新工作簿中。
    【解决方案2】:

    解决方案

     private static void ProcessTemplate(Stream template, Dictionary<string,string> toReplace)
            {
                using (var workbook = SpreadsheetDocument.Open(template, true, new OpenSettings { AutoSave = true }))
                {
    
                    workbook.WorkbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
                    workbook.WorkbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;
    
                    //Replace  SheetNames
                    foreach (Sheet sheet in workbook.WorkbookPart.Workbook.Sheets)
                        foreach (var key in toReplace.Keys)
                            sheet.Name.Value = sheet.Name.Value.Replace(key, toReplace[key]);
    
                    foreach (WorksheetPart wsheetpart in workbook.WorkbookPart.WorksheetParts)
                        foreach (SheetData sheetd in wsheetpart.Worksheet.Descendants<x.SheetData>())
                            foreach (Row r in wsheetpart.Worksheet.Descendants<x.Row>())
                                foreach (Cell c in r.Descendants<x.Cell>())
                                    if (c.CellFormula != null)
                                    {
                                        foreach (var key in toReplace.Keys)
                                            c.CellFormula.Text = c.CellFormula.Text.Replace(key, toReplace[key]);
                                    }
    
                                    // Replace shared strings
                                    SharedStringTablePart sharedStringsPart = workbook.WorkbookPart.SharedStringTablePart;
    
                    IEnumerable<x.Text> sharedStringTextElements = sharedStringsPart.SharedStringTable.Descendants<x.Text>();
                    for(int i =0;i<toReplace.Keys.Count; i++)
                        DoReplace(sharedStringTextElements, toReplace);
    
                    IEnumerable<x.Formula> sharedStringTextElementsF = sharedStringsPart.SharedStringTable.Descendants<x.Formula>();
                    for (int i = 0; i < toReplace.Keys.Count; i++)
                        DoReplaceFormula(sharedStringTextElementsF, toReplace);
    
                    // Replace inline strings
                    IEnumerable<WorksheetPart> worksheetParts = workbook.GetPartsOfType<WorksheetPart>();
                    foreach (var worksheet in worksheetParts)
                    {
    
                        var allTextElements = worksheet.Worksheet.Descendants<x.Text>();
                        DoReplace(allTextElements, toReplace);
    
                        var allTextElements2 = worksheet.Worksheet.Descendants<x.Formula>();
                        DoReplaceFormula(allTextElements2, toReplace);
    
                    }
    
                } // AutoSave enabled
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-28
      • 2017-03-13
      • 1970-01-01
      • 1970-01-01
      • 2015-07-22
      • 1970-01-01
      • 2012-05-04
      相关资源
      最近更新 更多