2014-01-24 75 views
0

我有公式單元格在具有公式= SUM(C2:C3)的Excel文件中。openxml sdk excel如何解析和計算公式

從託管在雲中遠程網絡服務器上的Web應用程序中,沒有安裝Excel,我會傳入C2和C3的值。

我也可以在excel中確定確切的公式。如何在c#中以編程方式解析此公式,以便如果C2和C3的輸入值分別爲2和4,我可以得到6的結果?

如果公式非常複雜,那麼解析公式並在asp.net mvc應用程序的服務器端用C#計算它的最佳方法是什麼?

在這種情況下,代碼示例真的會讓我受益。

回答

1

如果您提供了一個工具來打開excel文件並將其內容轉換爲html,您必須處理計算。

如果文件是「很好地創建」的,例如用Excel手動操作,你可以確定你不需要管理公式的計算,因爲excel可以做到這一點,並且將公式存儲在CellFormula的子元素中,並將結果存儲在CellValue的子元素(請參閱方法GetValue_D11())。所以基本上你只需要顯示結果..它總是一個字符串。

不幸的是,如果你想維護行爲,你必須處理樣式和數據類型。

其實你必須建立一個複雜的基於Web的電子表格查看器/編輯器。

下面是一個示例「fixed」(完全不是動態的),用於檢索字符串值和公式值。如果你想運行測試,一定要下載該文件(http://www.devnmore.com/share/Test.xlsx),否則它不能正常工作。

ShowValuesSample svs = new ShowValuesSample("yourPath\\Test.xlsx"); 
String[] test = svs.GetDescriptions_A2A10(); 
Double grandTotal = svs.GetValue_D11(); 

ShowValuesSample類:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using DocumentFormat.OpenXml.Packaging; 
using Ap = DocumentFormat.OpenXml.ExtendedProperties; 
using Vt = DocumentFormat.OpenXml.VariantTypes; 
using DocumentFormat.OpenXml; 
using DocumentFormat.OpenXml.Spreadsheet; 
using A = DocumentFormat.OpenXml.Drawing; 
using System.Globalization; 

namespace TesterApp 
{ 
    public class ShowValuesSample 
    { 

     public String FileName { get; private set; } 

     private SpreadsheetDocument _ExcelDocument = null; 
     public SpreadsheetDocument ExcelDocument 
     { 
      get 
      { 
       if (_ExcelDocument == null) 
       { 
        _ExcelDocument = SpreadsheetDocument.Open(FileName, true); 
       } 
       return _ExcelDocument; 
      } 

     } 
     private SheetData _SheetDataOfTheFirstSheet = null; 
     public SheetData SheetDataOfTheFirstSheet 
     { 
      get 
      { 
       if (_SheetDataOfTheFirstSheet == null) 
       { 
        WorksheetPart shPart = ExcelDocument.WorkbookPart.WorksheetParts.ElementAt(0); 
        Worksheet wsh = shPart.Worksheet; 
        _SheetDataOfTheFirstSheet = wsh.Elements<SheetData>().ElementAt(0); 
       } 

       return _SheetDataOfTheFirstSheet; 
      } 
     } 
     private SharedStringTable _SharedStrings = null; 
     public SharedStringTable SharedStrings 
     { 
      get 
      { 
       if (_SharedStrings == null) 
       { 
        SharedStringTablePart shsPart = ExcelDocument.WorkbookPart.SharedStringTablePart; 
        _SharedStrings = shsPart.SharedStringTable; 
       } 
       return _SharedStrings; 
      } 
     } 

     public ShowValuesSample(String fileName) 
     { 
      FileName = fileName; 
     } 

     //In the file descriptions are stored as sharedString 
     //so cellValue it's the zeroBased index of the sharedStringTable 
     //in my example i saved 9 different values 
     //sharedstring it's a trick to reduce size of a file obiouvsly writing 
     //repetitive string just once 
     public String[] GetDescriptions_A2A10() 
     { 
      String[] retVal = new String[9]; 

      for (int i = 0; i < retVal.Length; i++) 
      { 
       Row r = SheetDataOfTheFirstSheet.Elements<Row>().ElementAt(i + 1); 
       Cell c = r.Elements<Cell>().ElementAt(0); 
       Int32 shsIndex = Convert.ToInt32(c.CellValue.Text); 
       SharedStringItem shsItem = SharedStrings.Elements<SharedStringItem>().ElementAt(shsIndex); 
       retVal[i] = shsItem.Text.Text; 
      } 

      return retVal; 
     } 

     //The value it's stored beacause excel does 
     //To be sure it's correct you should perform all calculations 
     //In this case i'm sure Excel didn't stored the wrong value so.. 
     public Double GetValue_D11() 
     { 
      Double retVal = 0.0d; 

      Int32 cellIndex = 0; 
      //cellIndex it's 0 and not 3, cause A11, B11, C11 are empty cells 
      //Another issue to deal with ;-) 
      Cell c = SheetDataOfTheFirstSheet.Elements<Row>().ElementAt(10).Elements<Cell>().ElementAt(cellIndex); 

      //as example take a look at the value of storedFormula 
      String storedFormula = c.CellFormula.Text; 
      String storedValue = c.CellValue.Text; 

      NumberFormatInfo provider = new NumberFormatInfo(); 
      provider.NumberDecimalSeparator = "."; 
      provider.NumberGroupSeparator = ","; 
      provider.NumberGroupSizes = new Int32[] { 3 }; 

      retVal = Convert.ToDouble(storedValue, provider); 

      return retVal; 
     } 
    } 
} 
+0

你以前做過嗎?因爲我在這方面得到了很多理論上的答案,所以我沒有得到答案。對不起,因爲我一直在問類似的問題,並沒有得到任何地方而不高興。 –

+0

是的..有點當然。 ;-)你會得到理論上的答案,因爲你的問題聽起來像「我可以打開並閱讀html文件,我怎樣才能製作瀏覽器?」無論如何,看看這個,它可能會有所幫助。 http://stackoverflow.com/questions/21349678。 –

+0

感謝弗朗切斯科..我很抱歉,我有點苛刻..它只是,儘管多次嘗試在這..我不會去任何地方。感謝您的反饋意見。 –

0

恐怕不可能。在Open XML中,您可以閱讀或更改公式。但是,您可以通過打開xml來處理公式並獲得結果。

更改公式的C2和C3的值,然後將其保存在打開的xml中,現在通過Excel應用程序打開文檔。這些值將被計算和顯示。

請參閱本SO後,與此相關的問題open xml sdk excel formula recalculate cache issue

參考這個帖子太http://openxmldeveloper.org/discussions/formats/f/14/p/1806/158153.aspx

希望這有助於!

+0

我剛剛編輯我的問題,使用Excel應用程序打開Excel文件是不可能的。 –

+0

您可以修改更改,並在打開文件時更新它。如果你想執行計算和更新。爲計算創建單獨的方法並計算並存儲結果。 –

+0

說增加創建附加功能,並使用它來獲得結果並將其作爲值存儲在字段 –

1
spreadSheet.WorkbookPart.Workbook.CalculationProperties.ForceFullCalculation = true; 
spreadSheet.WorkbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true; 

爲我工作。