Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Move to old-code

svn path=/trunk/old-code/; revision=156205
  • Loading branch information...
commit 8352f77379694ab71b492fffe438b5532343be0c 1 parent fd3a432
@migueldeicaza migueldeicaza authored
View
74 wahid/Cell.cs
@@ -0,0 +1,74 @@
+//
+// Cell.cs
+//
+// Authors:
+// Miguel de Icaza (miguel@novell.com)
+//
+// Copyright 2008 Novell, Inc (http://www.novell.com).
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+
+namespace Wahid {
+
+ public class Cell {
+ public static Value DefaultValue = new StringValue ("");
+ public Sheet Sheet { get; private set; }
+
+ public int Col { get; set; }
+ public int Row { get; set; }
+
+ Value val;
+
+ /// <summary>
+ /// Internal constructor, must only be called by Sheet.CreateCell
+ /// </summary>
+ public Cell (Sheet sheet, int col, int row)
+ {
+ Sheet = sheet;
+ Col = col;
+ Row = row;
+ val = DefaultValue;
+ }
+
+ public Value Value {
+ get {
+ return val;
+ }
+
+ set {
+ val = value;
+ }
+ }
+
+ Formula formula;
+
+ public Formula Formula {
+ get {
+ return formula;
+ }
+
+ set {
+ formula = value;
+ }
+ }
+ }
+}
View
45 wahid/DirAccess.cs
@@ -0,0 +1,45 @@
+//
+// DirAccess.cs: primitive access to zip files, it must be unpacked.
+//
+// Authors:
+// Miguel de Icaza (miguel@novell.com)
+//
+// Copyright 2008 Novell, Inc (http://www.novell.com).
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System.IO;
+using System;
+
+namespace Wahid {
+ public class DirAccess : ZipAccess {
+ string loc;
+
+ public DirAccess (string loc)
+ {
+ this.loc = loc;
+ }
+
+ public override Stream Get (string resource)
+ {
+ return File.OpenRead (Path.Combine (loc, resource));
+ }
+ }
+}
View
180 wahid/Formula.cs
@@ -0,0 +1,180 @@
+//
+// Formula.cs
+//
+// Authors:
+// Miguel de Icaza (miguel@novell.com)
+//
+// Copyright 2008 Novell, Inc (http://www.novell.com).
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Text;
+
+namespace Wahid {
+
+ public class Formula {
+
+ class Tokenizer {
+ StringBuilder sb = new StringBuilder ();
+ int len;
+ int pos;
+ string s;
+ object putback;
+
+ public Tokenizer (string s)
+ {
+ this.s = s.Trim ();
+ len = s.Length;
+ }
+
+ double GetFraction (StringBuilder sb)
+ {
+ sb.Append (s[pos++]);
+ if (pos < len && Char.IsDigit (s [pos])){
+ while (pos < len && Char.IsDigit (s [pos]))
+ sb.Append (s [pos++]);
+ }
+ if (pos < len && s [pos] == 'e' || s [pos] == 'E'){
+ sb.Append (s [pos++]);
+ if (pos < len && s [pos] == '+' || s [pos] == '-')
+ sb.Append (s [pos++]);
+ if (pos < len && Char.IsDigit (s [pos]))
+ while (pos < len && Char.IsDigit (s [pos]))
+ sb.Append (s [pos++]);
+ }
+ return double.Parse (sb.ToString ());
+ }
+
+ double GetNumber ()
+ {
+ sb.Length = 0;
+
+ while (pos < len && Char.IsDigit (s [pos]))
+ sb.Append (s [pos++]);
+ if (pos < len && s [pos] == '.')
+ return GetFraction (sb);
+
+ return double.Parse (sb.ToString ());
+ }
+
+ ErrorValue TryError (string error, ErrorValue ret)
+ {
+ if (error == null)
+ throw new Exception ("Invalid error");
+
+ string sub = s.Substring (pos);
+
+ if (s.StartsWith (error)){
+ pos += error.Length;
+ return ret;
+ }
+ return null;
+ }
+
+ object GetToken ()
+ {
+ if (putback != null){
+ object p = putback;
+ putback = null;
+ return p;
+ }
+
+ while (pos < len){
+ char c = s [pos];
+
+ if (c >= '0' && c <= '9')
+ return GetNumber ();
+
+ if (c == '.'){
+ sb.Length = 0;
+ return GetFraction (sb);
+ }
+
+ if (c == '#'){
+ return TryError ("#DIV/0!", ErrorValue.DivisionByZero) ??
+ TryError ("#N/A!", ErrorValue.NA) ??
+ TryError ("#NAME?", ErrorValue.Name) ??
+ TryError ("#NULL?", ErrorValue.Null) ??
+ TryError ("#NUM!", ErrorValue.Num) ??
+ TryError ("#REF!", ErrorValue.Ref) ??
+ TryError (null, null);
+ }
+ if (c == '"'){
+ int start = ++pos;
+ while (pos < len && s [pos] != '"')
+ pos++;
+ if (pos < len)
+ return new StringValue (s.Substring (start, pos-start));
+ throw new Exception ("Unfinished quote");
+ }
+
+ if (c == ':' || c == ',' || c == ' ' || c == '^' || c == '*' || c == '/' || c == '+' ||
+ c == '-' || c == '&' || c == '=' || c == '%' || c == '[' || c == ']' || c == '!'){
+ pos++;
+ return c;
+ }
+
+ if (c == '>'){
+ if (pos + 1 < len && s [pos+1] == '='){
+ pos += 2;
+ return ">=";
+ }
+ pos++;
+ return '>';
+ }
+
+ if (c == '<'){
+ if (pos + 1 < len && s [pos+1] == '='){
+ pos += 2;
+ return "<=";
+ }
+
+ if (pos + 1 < len && s [pos+1] == '>'){
+ pos += 2;
+ return "<>";
+ }
+ pos++;
+ return '<';
+ }
+
+ if (c == '[' || c == ']'){
+ return c;
+ }
+
+
+ }
+ return null;
+ }
+
+ void PutBack (object a)
+ {
+ putback = a;
+ }
+ }
+
+
+ public Formula (string s)
+ {
+ // Parse the beast.
+ }
+ }
+}
View
13 wahid/Locale.cs
@@ -0,0 +1,13 @@
+namespace Wahid {
+
+ static class Helper {
+
+ /// <summary>
+ /// Allows C-like _("string") localization
+ /// </summary>
+ public static string _ (this object s)
+ {
+ return s.ToString ();
+ }
+ }
+}
View
9 wahid/Makefile
@@ -0,0 +1,9 @@
+SOURCES = Cell.cs Formula.cs Locale.cs Sheet.cs Workbook.cs ZipAccess.cs Value.cs xlsx.cs
+
+DESKTOP_SOURCES = DirAccess.cs
+
+wahid.exe: main.cs $(SOURCES) $(DESKTOP_SOURCES) Makefile
+ gmcs -debug -out:wahid.exe main.cs $(SOURCES) $(DESKTOP_SOURCES) -r:System.Xml.Linq -r:System.Core
+
+run: wahid.exe
+ mono --debug wahid.exe
View
44 wahid/README
@@ -0,0 +1,44 @@
+Wahid - A Spreadsheet engine
+----------------------------
+
+ This is spreadsheet engine, initially without a GUI.
+
+ Ideally a number of user interfaces can be built on top of the
+ spreadsheet engine:
+
+ * Silverlight (like Google's spreadsheets)
+
+ * gui.cs (the most powerful and awesome RIA in the world)
+
+ * command-line, to compute, and convert data.
+
+ * Gnome (worth doing?)
+
+OOXML
+-----
+
+ Am drawing inspiration form the OOXML specification on how to
+ structure the internals of this engine, but the idea is to
+ have multiple importers and expoters.
+
+ Currently the code does not even unzip archives, it expects a
+ directory called "test" to contain an unzipped OOXML file (I
+ used the gnumeric test files for this).
+
+ The Zip support is split from the loader as in Silverlight we
+ would want to use the Downloader class to unzip the files for
+ us, while on the desktop we can use SharpZipLib.
+
+Models and Views
+----------------
+
+ The engine will communicate with the views through events that
+ the views connect to.
+
+ In addition to the usual support for views for multiple
+ spreadsheets, this will be useful to have views and
+ controllers that can be connected on the backend to a server.
+ This would allow multiple users to edit the spreadsheet
+ simultaneously.
+
+
View
73 wahid/Sheet.cs
@@ -0,0 +1,73 @@
+//
+// Cell.cs
+//
+// Authors:
+// Miguel de Icaza (miguel@novell.com)
+//
+// Copyright 2008 Novell, Inc (http://www.novell.com).
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+
+namespace Wahid {
+
+ public class Sheet {
+ public string Name;
+ public int Id;
+
+ Dictionary<long,Cell> cells;
+
+ static long MakeKey (Cell cell)
+ {
+ return (cell.Col << 32) | cell.Row;
+ }
+
+ public Sheet (string name, int id)
+ {
+ if (name == null)
+ throw new ArgumentNullException ("name");
+
+ this.Name = name;
+ this.Id = id;
+
+ cells = new Dictionary<long,Cell> ();
+ }
+
+
+ public Cell CreateCell (int col, int row)
+ {
+ var cell = new Cell (this, col, row);
+
+ Attach (cell);
+
+ return cell;
+ }
+
+ public void Attach (Cell cell)
+ {
+ long k = MakeKey (cell);
+
+ cells [k] = cell;
+ }
+ }
+}
+
View
106 wahid/Value.cs
@@ -0,0 +1,106 @@
+//
+// Value.cs
+//
+// Authors:
+// Miguel de Icaza (miguel@novell.com)
+//
+// Copyright 2008 Novell, Inc (http://www.novell.com).
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System.Xml.Linq;
+
+namespace Wahid {
+
+ public class Value {
+ }
+
+ public class BoolValue : Value {
+ public bool Value;
+
+ public BoolValue (bool v)
+ {
+ this.Value = v;
+ }
+
+ public static implicit operator BoolValue (bool v)
+ {
+ return new BoolValue (v);
+ }
+ }
+
+ public class ErrorValue : Value {
+ public string Error;
+
+ public static ErrorValue DivisionByZero = new ErrorValue ("#DIV/0!");
+ public static ErrorValue NA = new ErrorValue ("#NA");
+ public static ErrorValue Name = new ErrorValue ("#NAME?");
+ public static ErrorValue Null = new ErrorValue ("#NULL?");
+ public static ErrorValue Num = new ErrorValue ("#NUM!");
+ public static ErrorValue Ref = new ErrorValue ("#REF!");
+
+ public ErrorValue (string v)
+ {
+ Error = v;
+ }
+ }
+
+ public class StringValue : Value {
+ public string Value;
+
+ public StringValue (string v)
+ {
+ this.Value = v;
+ }
+
+ public static implicit operator StringValue (string s)
+ {
+ return new StringValue (s);
+ }
+ }
+
+ public class RichStringValue : Value {
+ public XElement Value;
+
+ public RichStringValue (XElement x)
+ {
+ this.Value = x;
+ }
+
+ public static implicit operator RichStringValue (XElement d)
+ {
+ return new RichStringValue (d);
+ }
+ }
+
+ public class NumberValue : Value {
+ public double Value;
+
+ public NumberValue (double v)
+ {
+ Value = v;
+ }
+
+ public static implicit operator NumberValue (double d)
+ {
+ return new NumberValue (d);
+ }
+ }
+}
View
61 wahid/Workbook.cs
@@ -0,0 +1,61 @@
+//
+// Workbook.cs
+//
+// Authors:
+// Miguel de Icaza (miguel@novell.com)
+//
+// Copyright 2008 Novell, Inc (http://www.novell.com).
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+
+namespace Wahid {
+
+ public class Workbook {
+
+ public bool Dirty { get; set; }
+
+ public Dictionary<int,Sheet> Sheets { get; private set; }
+
+ public Workbook () : this (0)
+ {
+ }
+
+ public Workbook (int sheets)
+ {
+ Sheets = new Dictionary<int,Sheet> ();
+
+ for (int i = 0; i < sheets; i++){
+ //var s = new Sheet (String.Format (_("Sheet {0}"), i));
+ }
+ }
+
+ public Sheet CreateSheet (string name, int id)
+ {
+ if (Sheets.ContainsKey (id))
+ throw new ArgumentException ("Workbook already contains sheet with this id", "id");
+
+ return Sheets [id] = new Sheet (name, id);
+ }
+ }
+}
+
View
17 wahid/ZipAccess.cs
@@ -0,0 +1,17 @@
+using System;
+using System.IO;
+
+namespace Wahid {
+
+ //
+ // A simple wrapper, so we can have multiple loaders later
+ //
+ public abstract class ZipAccess {
+
+ public ZipAccess ()
+ {
+ }
+
+ public abstract Stream Get (string resource);
+ }
+}
View
14 wahid/main.cs
@@ -0,0 +1,14 @@
+using System;
+using Wahid;
+using Wahid.SpreadsheetML;
+
+class Test {
+ static void Main ()
+ {
+ Xlsx xlsx = Xlsx.Load ("test");
+ if (xlsx.Error == null)
+ Console.WriteLine ("Success");
+ else
+ Console.WriteLine ("Result: " + xlsx.Error);
+ }
+}
View
350 wahid/xlsx.cs
@@ -0,0 +1,350 @@
+//
+// xlsx.cs: Support for loading OOXML spreadsheets
+//
+// Authors:
+// Miguel de Icaza (miguel@novell.com)
+//
+// Copyright 2008 Novell, Inc (http://www.novell.com).
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+using System.Linq;
+using System.Xml;
+using System.Xml.Linq;
+using System.Xml.XPath;
+
+
+using System.Reflection;
+
+namespace Wahid.SpreadsheetML {
+
+ public enum CellType {
+ Boolean,
+ Error,
+ InlineString, // value inside <is> not inside <v> in the cell.
+ Number,
+ SharedString,
+ FormulaString
+ }
+
+ public class LoadException : Exception {
+ public LoadException (string msg) : base (msg) {}
+ }
+
+ public class Relationship {
+ public enum RType {
+ SharedStrings,
+ Worksheet,
+ Styles,
+ Theme,
+ CalcChain,
+ Unknown
+ }
+
+ public string Id;
+ public string Target;
+ public RType Type;
+
+ public static RType Lookup (string s)
+ {
+ switch (s){
+ case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings":
+ return RType.SharedStrings;
+ case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet":
+ return RType.Worksheet;
+ case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles":
+ return RType.Styles;
+ case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme":
+ return RType.Theme;
+ case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain":
+ return RType.CalcChain;
+ }
+ return RType.Unknown;
+ }
+
+ public Relationship (RType type, string id, string target)
+ {
+ Id = id;
+ Target = target;
+ Type = type;
+ }
+
+ }
+
+ static public class OOXML {
+ public static XNamespace ns_workbook = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
+ public static XNamespace ns_rels = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
+
+ public static XName c = "c";
+ public static XName f = ns_workbook + "f";
+ public static XName r = "r";
+ public static XName s = "s";
+ public static XName t = "t";
+ public static XName v = ns_workbook + "v";
+ public static XName is_ = "is";
+
+ public static void ParseReference (string s, out int col, out int row)
+ {
+ col = 0;
+ row = 0;
+
+ if (s == null)
+ return;
+
+ foreach (char c in s){
+ if (c >= 'A' && c <= 'Z'){
+ col = col * 26 + ((int) c) - 'A';
+ } else {
+ row = row * 10 + ((int) c - '0');
+ }
+ }
+ }
+
+ public static CellType GetCellType (XElement xcell, CellType defvalue)
+ {
+ string type = (string) xcell.Attribute (t);
+
+ switch (type){
+ case "b":
+ return CellType.Boolean;
+ case "e":
+ return CellType.Error;
+ case "inlineStr":
+ return CellType.InlineString;
+ case "n":
+ return CellType.Number;
+ case "s":
+ return CellType.SharedString;
+ case "str":
+ return CellType.FormulaString;
+ case null:
+ return defvalue;
+ }
+ throw new LoadException ("Unknown type for cell: " + type);
+ }
+ }
+
+ public class Xlsx {
+ public Workbook Workbook { get; private set; }
+ public string Error { get; private set; }
+
+ Dictionary<string,Relationship> relationships;
+ List<Value> sharedstrings;
+
+ ZipAccess loader;
+
+ public static Xlsx Load (string filename)
+ {
+ Xlsx x = new Xlsx (new DirAccess (filename));
+
+ x.Load ();
+
+#if false
+ try {
+ } catch (Exception e){
+ if (x.Error == null)
+ x.Error = "Generic loading error";
+ x.Error += e;
+ x.Workbook = null;
+ }
+#endif
+
+ return x;
+ }
+
+ Xlsx (ZipAccess loader)
+ {
+ Workbook = new Workbook ();
+ this.loader = loader;
+ Error = null;
+ }
+
+ TextReader Get (string part)
+ {
+ try {
+ return new StreamReader (loader.Get (part));
+ } catch {
+ Error = "Failure to retrieve part " + part;
+ throw new LoadException (Error);
+ }
+ }
+
+ class Dingus {
+ public Dingus (string s)
+ {
+ Console.WriteLine (s);
+ }
+ }
+
+ void LoadRelationships ()
+ {
+ relationships = new Dictionary<string,Relationship> ();
+
+ XElement xrel = XElement.Load (Get ("xl/_rels/workbook.xml.rels"));
+
+ var x =
+ from rel in xrel.Elements ()
+ let type = Relationship.Lookup ((string) rel.Attribute ("Type"))
+ where type != Relationship.RType.Unknown
+ select new Relationship (type,
+ (string) rel.Attribute ("Id"),
+ (string) rel.Attribute ("Target"));
+ relationships = x.ToDictionary (f => f.Id);
+ }
+
+ void LoadSharedStrings ()
+ {
+ sharedstrings = new List<Value> ();
+
+ XElement xsharedstrings = null;
+
+ try {
+ xsharedstrings = XElement.Load (Get ("xl/sharedStrings.xml"));
+ } catch {
+ // not an error to not have sharedStrings
+ return;
+ }
+
+ foreach (var ssi in xsharedstrings.Elements ()){
+ XElement first = ssi.FirstNode as XElement;
+
+ if (first.Name == OOXML.t)
+ sharedstrings.Add (new StringValue (first.Value));
+ else
+ sharedstrings.Add (new RichStringValue (first));
+ }
+ }
+
+ void LoadSheetData (Sheet sheet, XElement xsheetData)
+ {
+ // <row>
+ foreach (XElement xrow in xsheetData.Elements ()){
+ int row = Int32.Parse ((string) xrow.Attribute ("r"));
+
+ // <c>
+ foreach (XElement xcell in xrow.Elements ()){
+ int cell_col, cell_row;
+
+ // r=
+ OOXML.ParseReference ((string) xcell.Attribute (OOXML.r), out cell_col, out cell_row);
+
+ if (row != cell_row){
+ // this should not happen
+
+ Error = "Document contains cell references outside of their row";
+ throw new Exception ();
+ }
+
+ Cell cell = sheet.CreateCell (cell_col, cell_row);
+
+ //CellType type = OOXML.GetCellType (xcell, CellType.Number);
+ string type = (string) xcell.Attribute (OOXML.t);
+
+ foreach (XElement cval in xcell.Elements ()){
+ if (type == "inlineStr"){
+ if (cval.Name == OOXML.is_)
+ cell.Value = new RichStringValue (cval);
+ else
+ throw new LoadException ("Cell type is InlineString, but found other values");
+ }
+
+ if (cval.Name == OOXML.f){
+ cell.Formula = new Formula (cval.Value);
+ continue;
+ }
+
+ if (cval.Name == OOXML.v){
+ string s = cval.Value;
+ bool v;
+
+ switch (type){
+ case "b":
+ if (bool.TryParse (s, out v))
+ cell.Value = new BoolValue (v);
+ else
+ cell.Value = new BoolValue (int.Parse (s) == 1);
+ break;
+
+ case "e":
+ cell.Value = new ErrorValue (s);
+ break;
+
+ case "n":
+ cell.Value = new NumberValue (double.Parse (s));
+ break;
+
+ case "s":
+ // Lookup the string in the share string table
+ cell.Value = sharedstrings [Int32.Parse (s)];
+ break;
+
+ case "str":
+ cell.Value = new StringValue (cval.Value);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void LoadSheet (Sheet sheet, XElement xsheet)
+ {
+ XName xcols = OOXML.ns_workbook + "cols";
+ XName xsheetData = OOXML.ns_workbook + "sheetData";
+
+ foreach (XElement se in xsheet.Elements ()){
+ if (se.Name == xsheetData)
+ LoadSheetData (sheet, se);
+ }
+ }
+
+ void LoadWorkbook ()
+ {
+ XElement xwork = XElement.Load (Get ("xl/workbook.xml"));
+
+ // Since Linq.XPath is not working, work around it
+ var sheets_and_sources = from l in xwork.Elements ()
+ let xsheets = OOXML.ns_workbook + "sheets"
+ let xrid = OOXML.ns_rels + "id"
+ where l.Name == xsheets
+ from s in l.Elements ()
+ let rtarget = relationships [(string) s.Attribute (xrid)].Target
+ let sheet = Workbook.CreateSheet ((string)s.Attribute ("name"),
+ (int) s.Attribute ("sheetId"))
+ select new { sheet, rtarget } ;
+
+ foreach (var ss in sheets_and_sources)
+ LoadSheet (ss.sheet, XElement.Load (Get ("xl/" + ss.rtarget)));
+ }
+
+ void Load ()
+ {
+ LoadRelationships ();
+ // LoadStyle ();
+ LoadSharedStrings ();
+ LoadWorkbook ();
+ }
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.