(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

An Excel file Viewer in Silverlight

(12 votes)
Walter Ferrari
>
Walter Ferrari
Joined Dec 17, 2009
Articles:   19
Comments:   12
More Articles
29 comments   /   posted on Jan 25, 2010
Categories:   Line-of-Business , General

This article is compatible with the latest version of Silverlight.


Introduction

Let’s imagine a scenario in which you have a series of Excel files (.xlsx) on your computer but you don’t have any Microsoft Office installed. What can we do if we want to examine the content of these files?
In this article we will describe a small Silverlight application allowing you to open and view these files and also create line series graphs. I used this exercise as laboratory to familiarize myself with some of the new features of Silverlight like, for instance, drag&drop of files from local folders to the application, drag&drop between controls in the application, right click event handling, theming and so on. I also used the Chart control from the Silverlight toolkit and I extended it by adding zoom +, zoom – and the zoom window functionality. Obviously this application is not intended as a complete and stable product. In fact, it is limited to the Excel files, which are not too big and complicated, and it is at an early stage, not bug free - nevertheless I hope that it can be a decent example capable of showing what can we do with Silverlight 4 and a good starting point for someone who wants to extend it and improve it.
Here you can watch a video showing how to use the Silverlight application and here you can try it by yourself. Here you can download the source code.

The User Interface

The UI is very simple and it is made of two columns; the tight column on the left contains a TreeView Control and the larger column in the centre contains a Tab Control. You can interact with the interface at the beginning by simply dragging the Excel files from your local folder to the TreeView. Consequently, the TreeView will be populated with a series of items and sub-items corresponding respectively to the name of the files and the name of their sheets. A click on one of these items or sub-items causes the creation of a Tab Control on the central area with a number of tabs equalling the number of sheets in the xlsx file selected.

A DataGrid overtopped by a Chart and an Expander Control are put on each tab. The DataGrid is filled up with the data contained in the sheet selected, assuming that the first row contains the headers of the columns (I recognize this is a very rough simplification). At this stage you can either build a graph using the options contained in the Expander Control (i.e. choosing the independent column and the dependent column and then pressing the button “Build”) or drag & drop items of the rows selected from the Datagrid to the Chart. Actually, this last operation is a bit tricky due to the standard behaviour of the Datagrid: you have to click on the first row of the selection you want and, keeping pressed the shift key, click again on the final row of your selection and finally without releasing the left mouse button drag the selection just created and drop it on top of the Chart. The Chart will be populated with all the data suitable found in the selection.
The Chart Control has been extended with some additional functionalities; a right click on the Chart area shows a contextual menu with the already mentioned features (zoom +, zoom – and zoom window ) ; the icon cursor changes accordingly to your choice.

Excel Viewer UI

Main points of interest

Surely the first problem that I had to solve was the reading of the excel file, then the way in which the data can be put in the Datagrid. Other interesting points are how to manage the drag & drop operations between local folders and the Silverlight application and between controls inside the application. Finally, 2 difficult points were, on the one hand, the transformation of the data dragged from the Datagrid to an observable Collection compatible with the Chart control and, on the other hand, the implementation of the zooming functionalities.

How to read the Excel (*.xlsx) files

A good starting point is a series of great articles from rmaclean’s blog which couldn’t explain better how to work with the xlsx Excel 2007 native file format. Essentially a .xlsx file is composed of a zip file and a series of xml files containing information on what is inside the zip. You can refer to these articles for further investigation. I based my implementation of these hints starting with a public Interface which exposes the following methods:

 public interface IFileDropFormat
     {
         string GetFilename();
         List<string> GetListSubItems();
         IEnumerable<IDictionary> GetData(string itemSelected);
     }

The first method does not need any explanation, the second instead (GetListSubItems() ) let’s presume that the generic file dropped can be composed of subitems and the third suggests that we should be able to get an Ienumerable<IDictionary> of the data in the file for each sub-item considered. The structure of an xlsx file follows this scheme: each sheet is a sub-item containing data.
Upon this Interface I built a class (XLSXReader) to read the Excel files. The method GetData(…) is implemented as follows:

 public IEnumerable<IDictionary> GetData(string itemSelected)
 {
     int worksheetIdex = GetWorksheetIndex(itemSelected);
  
     if (worksheetIdex <= 0)
         yield break;
 
     XElement wsSelectedElement = GetWorksheet(worksheetIdex);
     if (wsSelectedElement == null)
         yield break;
     IEnumerable<XElement> rowsExcel = from row in wsSelectedElement.Descendants(XLSXReader.excelNamespace + "row")
                                      select row  ;
     if (rowsExcel == null)
         yield break;
  
     foreach (XElement row in rowsExcel)
     {
         var dict = new Dictionary<string, object>();
         IEnumerable<XElement> cellsRow = row.Elements(XLSXReader.excelNamespace + "c");
         foreach (XElement cell in cellsRow)
         {
             if (cell.HasElements == true)
             {
                 string cellValue = cell.Element(XLSXReader.excelNamespace + "v").Value;
                 if (cell.Attribute("t") != null)
                 {
                     if (cell.Attribute("t").Value == "s")
                     {
                         cellValue = sharedStrings[Convert.ToInt32(cellValue)];
                     }
                 }
  
                 dict[cell.Attribute("r").Value.Substring(0, 1)] = cellValue as Object;
             }
         }
         yield return dict;
     }         
 }

In the code portion above, firstly we obtain an XElement representing the worksheet selected and then we extract an IEnumerable(rowsExcel ) in order to walk all the rows in the worksheet and create the IEnumerable<IDictionary> requested.

Binding to Datagrid

To bind the IEnumerable<Dictionary> to the Datagrid I drew inspiration from this article which suggests using the class provided by Vladimir Bodurow in his blog. Essentially this class transforms each dictionary key into a property of anonymous typed object.

In the following portion of code we proceed adding the columns to the Datagrid assuming (as we already outlined in the introduction) that the first row of data in the Excel file contains the header columns name; then we transform the IEnumerable<IDictionary> to a datasource using the class above mentioned and skipping the first item since it has already been used for the headers. The datasource is finally bound to the ItemSource property to the Datasource.

 public void UpdateMainGrid()
 {
     if (MainGridElement == null)
         return;
  
     IEnumerable<IDictionary> datasource = FileDropped.GetData(ItemSelected);
  
     MainGridElement.Columns.Clear();
  
     if (datasource.Count() == 0)
     {
         MainGridElement.Columns.Add(
             new DataGridTextColumn
             {
                 Header = "There are no items!",
                 Binding = new Binding("")
             });
         MainGridElement.ItemsSource = "";
  
         return;
     }
  
     // create columns
     IDictionary firstRow = null;
  
     try{
         firstRow = datasource.First();
     }
     catch{
         return;
     }
  
     foreach (DictionaryEntry pair in firstRow)
     {
         MainGridElement.Columns.Add(
             new DataGridTextColumn
             {
                 Header = pair.Value,
                 Binding = new Binding(pair.Key.ToString())
             });
     }
     // we assume that the first column contains the headers of the columns
     MainGridElement.ItemsSource = datasource.Skip(1).ToDataSource();
 }

Drag & Drop operations

The first Drag & Drop considered is between a local folder and the TreeView Control; first of all we need to set to true the AllowDrop property of the TreeView and then manage the event concerned. This is carried out by the Method ManageDrop(..) here below:

 public static void ManageDrop(object sender, RoutedEventArgs e)
 {
     DragEventArgs dr = e as DragEventArgs;
     string objectName = GetSenderName(sender);
  
     if (dr.Data == null)
         return;
  
     IDataObject dataObject = dr.Data as IDataObject;
     FileInfo[] files = dataObject.GetData(DataFormats.FileDrop) as FileInfo[];
  
     foreach (FileInfo file in files)
     {
         // open Excel file
         if (file.Name.EndsWith("xlsx"))
         {
             XLSXReader xlsxReader = new XLSXReader(file);
  
             List<string> subItems = xlsxReader.GetListSubItems();
             
             if (droppedFiles == null)
                 droppedFiles = new Dictionary<string, IFileDropFormat>();
             if (droppedFiles.ContainsKey(file.Name) == false)
                 droppedFiles.Add(file.Name, xlsxReader);
         }
     }
     MainPage myPage = App.Current.RootVisual as MainPage;
     foreach (KeyValuePair<string, IFileDropFormat> keyValuePair in droppedFiles)
     {
         if (myPage != null)
         {
             myPage.dfvFilesList.AddItems(keyValuePair.Value.GetListSubItems(), keyValuePair.Key);
         }
     }
 }

The second drag & drop between the Datagrid and the Chart Control is more interesting and the obstacles that we had to face were pretty challenging. Firstly in the generic.xaml file of the main project from one side and in the generic.xaml of the library containing the extended version of the Chart, we surrounded the two controls with respectively a DataGridDragDropTarget and a DataPointSeriesDragDropTarget control. The two controls are available in the Silverlight Toolkit and add all the necessary support to this kind of tasks.

 <!-- Datagrid with drag&drop support -->
 <ControlTemplate TargetType="dfv:dfvDatagrid">
      <my3:DataGridDragDropTarget x:Name="MainGridDragDropElement" HorizontalAlignment="Stretch">
          <my2:DataGrid x:Name="MainGridElement"  AllowDrop="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible" AutoGenerateColumns="False"  HorizontalAlignment="Stretch"/>
      </my3:DataGridDragDropTarget>
  </ControlTemplate>
  
 <!-- Chart with drag&drop support -->
 <toolkitDD:DataPointSeriesDragDropTarget x:Name="MainChartDragDropElement" AllowDrop="true" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
      <toolkitDD:Chart AllowDrop="True"   x:Name="MainChartElement"/>
 </toolkitDD:DataPointSeriesDragDropTarget>

Then, obviously we had to set to true the property AllowDrop on both the controls. In the codebehind we added the MainChartDragDrop_doDrop event to the DragEventHandler of the DataPointSeriesDragDropTarget control:

 private void MainChartDragDrop_doDrop(object sender, Microsoft.Windows.DragEventArgs e)
 {
     if (e.Data == null)
         return;
  
     object drArgs = e.Data.GetData("System.Windows.Controls.ItemDragEventArgs");
  
     if (drArgs == null)
         return;
  
     ItemDragEventArgs dataDropped = drArgs as ItemDragEventArgs;
  
     if (dataDropped == null)
         return;
   
     SelectionCollection selectedData = dataDropped.Data as SelectionCollection;
  
     if (selectedData == null)
         return;
  
     BuildGraphFromDrop(selectedData);
 }

With this method we make a series of steps in order to come to a Collection of objects of type SelectionCollection. A SelectionCollection is actually the way in which the DragDropTarget controls store the objects selected. What we need to do now is transform this SelectionCollection into a ObservableCollection linked to the Chart. This is done in the BuildGraphFromDrop(…) method.

 private void BuildGraphFromDrop(SelectionCollection droppedData)
 {
     IEnumerator<Selection> ieSel = droppedData.GetEnumerator();
 
     // let's get the number of series (or columns) included in the data dropped
     ieSel.MoveNext();
     PropertyInfo[] propInfo = ieSel.Current.Item.GetType().GetProperties();
     int columnsNumber = propInfo.Count();
  
     for (int i = 0; i < columnsNumber - 1; i++)
         _dynItemsSource.Add(new ObservableCollection<Pair>());
  
     // reset any data linked to the chart
     foreach (ObservableCollection<Pair> pairCollection in _dynItemsSource)
         pairCollection.Clear();
  
     object _first = double.NaN;
     object _second = double.NaN;
     double firstMin, firstMax, secondMin, secondMax;
     firstMin = firstMax = secondMin = secondMax = double.NaN;
  
     // let's navigate through each item of the SelectionCollection (which represents a row in the datagrid)
     // and fill the observable collection created just before
     foreach (Selection sel in droppedData)
     {
        for (int i = 0; i < columnsNumber; i++)
         {
 28:            object cellvalue = sel.Item.GetType().GetProperties()[i].GetValue(sel.Item, null);
             double dblValue;
             if (ComparerHelper.TryConvertToDouble(cellvalue, out dblValue))
             {
                 if (i == 0) // we assume the first column as the independent column
                 {
                     _first = dblValue;
                     firstMin = double.IsNaN(firstMin) ? dblValue : firstMin;
                     firstMin = firstMin > dblValue ? dblValue : firstMin;
                     firstMax = double.IsNaN(firstMax) ? dblValue : firstMax;
                     firstMax = firstMax < dblValue ? dblValue : firstMax;
                 }
                 else
                 {
                     _second = dblValue;
  
                     secondMin = double.IsNaN(secondMin) ? dblValue : secondMin;
                     secondMin = secondMin > dblValue ? dblValue : secondMin;
                     secondMax = double.IsNaN(secondMax) ? dblValue : secondMax;
                     secondMax = secondMax < dblValue ? dblValue : secondMax;
  
                     Pair newPairValue = new Pair { First = _first, Second = _second };
                     _dynItemsSource[i - 1].Add(newPairValue);
                 }
             }
             else
             {
                 _first = double.NaN;
             }
  
         }
     }
  
     // Add Axes
     MainChartElement.Axes.Clear();
  
     double rangeX = Math.Abs(firstMax - firstMin);
     double rangeY = Math.Abs(secondMax - secondMin);
     IAxis myAxisX = new LinearAxis
     {
         Orientation = AxisOrientation.X,
         Minimum = firstMin - rangeX / 10,
         Maximum = firstMax + rangeX / 10,
         ShowGridLines = true
     };
     MainChartElement.Axes.Add(myAxisX);
  
     IAxis myAxisY = new LinearAxis
     {
         Orientation = AxisOrientation.Y,
         Minimum = secondMin - rangeY / 10,
         Maximum = secondMax + rangeY / 10,
         ShowGridLines = true
     };
     MainChartElement.Axes.Add(myAxisY);
  
     MainChartElement.Series.Clear();
     int seriesNum = 0;
     foreach (ObservableCollection<Pair> newPairCollection in _dynItemsSource)
     {
         LineSeries mySerie = new LineSeries();
         mySerie.Name = "Serie" + seriesNum.ToString();
         mySerie.Title = "";
         seriesNum += 1;
  
         mySerie.ItemsSource = newPairCollection;
         mySerie.IndependentValueBinding = new Binding("First");
         mySerie.DependentValueBinding = new Binding("Second");
  
         //
         MainChartElement.Series.Add(mySerie);
  
         MainChartElement.Title = FileDropped.GetFilename();
         MainChartElement.LegendTitle = "Legend";
     } 
 }

As you may see, first we determine the number of columns included in the selection and then we cycle on each Selection item of the SelectionCollection to populate a List of ObservableCollection objects (_dynItemsSource); this List is defined as follows:

private List<ObservableCollection<Pair>> _dynItemsSource;

The class Pair, which represents a couple of values (the dependent and independent values of a LineSerie) is defined as follow:

 public class Pair : INotifyPropertyChanged,  IComparable
 {
     private object _first;
     private object _second;
     private static PairSortMethod _sortOrder;


     /// <summary>
     /// Gets or sets the first value.
     /// </summary>
     public object First
     {
         get
         {
             return _first;
         }
         set
         {
             _first = value;
             OnPropertyChanged("First");
         }
     }
  
     /// <summary>
     /// Gets or sets the second value.
     /// </summary>
     public object Second
     {
         get
         {
             return _second;
         }
         set
         {
             _second = value;
             OnPropertyChanged("Second");
         }
     }
  
     /// <summary>
     /// Implements the INotifyPropertyChanged interface.
     /// </summary>
     public event PropertyChangedEventHandler PropertyChanged;
  
     /// <summary>
     /// Fires the PropertyChanged event.
     /// </summary>
     /// <param name="propertyName">Name of the property that changed.</param>
     private void OnPropertyChanged(string propertyName)
     {
         PropertyChangedEventHandler handler = PropertyChanged;
         if (null != handler)
         {
             handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
         }
     }
  
     public static PairSortMethod SortOrder
     {
         get { return _sortOrder; }
         set { _sortOrder = value; }
     }         
     int IComparable.CompareTo(object obj)
     {
         if (obj is Pair)
         {
             Pair p2 = (Pair)obj;
   
             return ((Double)First).CompareTo(p2.First) + ComparerHelper.PairComparison(Second, p2.Second);
         }
         else
             throw new ArgumentException("Object is not a Pair.");
     }
 }

It is important to underline that the items in the SelectionCollection are objects of a type generated at runtime ( TempType objects) and need to be converted where possible to double values; this is why we try to convert them (with TryConvertToDouble) before the insertion.

In other words, on the basis of the SelectionCollection returned, we build a List of ObservableCollection objects which we then link to the Chart control. In detail, we build as many LineSeries objects as the number of ObservableCollection objects, we link the ItemsSource property of each LineSerie to an ObservableCollection of Pair and indicate that the independent values and dependent values of each LineSerie coincide with elements “First” and “Second” of the class Pair. Behind the scene here we are making assuming that the first column of our Datagrid (and obviously of our worksheet)contains the independent values and all the other columns consist of dependent values. This is indeed a simplification, but it shouldn’t be too difficult to add some kind of interactivity to allow the user to choose a column different from the independent column. Limited to a single LineSerie this can be done by using the panel on the left of the Chart control.
The Chart is finally completed by adding the Axes and all the LineSeries instantiated.

Zooming on the Chart

To add the zoom functionality to the Chart control of the Silverlight Toolkit I first inserted the Chart in a Canvas Control. The main reason for that is the possibility to use the local coordinate system of the Canvas to draw a semitransparent rectangle when the user chooses the option “zoom window” from the contextual menu. This rectangle gives guidance to the user in terms of the size of the window he wants.

The core of the mechanism of zooming is common to the tree zoom options: basically we change the minimum and maximum value of the LinearAxis along X and Y and then the Chart changes its scale accordingly. The hardest part is to understand that we must make two conversions between three coordinate systems. The first coordinate system is the one used by the method GetPlotAreaCoordinate(…) of the Chart; the second is the one of the UIElement used to obtain the mouse coordinate with GetPositionUIElement …); finally the third refers to the values of data series. So, as you can see below, we first need to transform the coordinates of the point clicked from the coordinate system of the LineSeries (the UIEement we chose as reference) to the one used by GetPlotAreaCoordinate(…) and this is, by the way, a simple translation of axes. Then we have to calculate the scale factor between pixels and data values and perform a scale conversion.

 private void ZoomWindowChart(MouseButtonEventArgs e)
 {
     LineSeries myLS = MainChartElement.Series[0] as LineSeries;
     Point endPoint = e.GetPosition(myLS);
  
     LinearAxis xAxis = MainChartElement.Axes[0] as LinearAxis;
     LinearAxis yAxis = MainChartElement.Axes[1] as LinearAxis;
  
     // values range of both axes
     double rangeX = Math.Abs(Convert.ToDouble(xAxis.ActualMaximum - xAxis.ActualMinimum));
     double rangeY = Math.Abs(Convert.ToDouble(yAxis.ActualMaximum - yAxis.ActualMinimum));
  
     // extent of the graph in pixel
     double pixelExtentX = Math.Abs((xAxis.GetPlotAreaCoordinate(Math.Abs((double)xAxis.ActualMaximum))).Value);
     double pixelExtentY = Math.Abs((yAxis.GetPlotAreaCoordinate(Math.Abs((double)yAxis.ActualMaximum))).Value); 
     // calculate scale factor for both axes
     double xScalePixelFactor = rangeX / pixelExtentX;
     double yScalePixelFactor = rangeY / pixelExtentY;
  
     // calculate offset
     double xOffset = xAxis.GetPlotAreaCoordinate(0.0).Value;
     double yOffset = yAxis.GetPlotAreaCoordinate(0.0).Value;
  
     // new min & max values of the graph
     xAxis.Minimum = (Math.Min(startPoint.X, endPoint.X) - xOffset) * xScalePixelFactor;
     xAxis.Maximum = (Math.Max(startPoint.X, endPoint.X) - xOffset) * xScalePixelFactor;
     yAxis.Minimum = (pixelExtentY - Math.Max(startPoint.Y, endPoint.Y) - yOffset) * yScalePixelFactor;
     yAxis.Maximum = (pixelExtentY - Math.Min(startPoint.Y, endPoint.Y) - yOffset) * yScalePixelFactor;
     
     SelectionElement.Visibility = Visibility.Collapsed;
  
 }

Summary

In this article we have seen how to build a simple excel files viewer using the new features of Silverlight 4 and some controls included in the Silverlight toolkit. In particular, we have showed how to handle drag & drop of files between local folders and a Silverlight application and also drag & drop of data between two Silverlight controls (Datagrid and Chart). We have also showed how it is possible to easily extend control chart and add functionalities to the zoom. As I wrote at the beginning, the application is at an early stage and I am planning to improve it following the suggestions made by Jose Almoguera in the final part of his article, in particular with regards to the ExcelReader project and the possibility to convert it to Silverlight.


Subscribe

Comments

  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by Fallon on Jan 25, 2010 23:52
    The Zip File is Corrupt.
  • walterf

    RE: An Excel file Viewer in Silverlight 4


    posted by walterf on Jan 26, 2010 00:19

    I see...

    sorry for that. Use this link: http://www.snello.it/samples/ExcelViewer/Excel_viewer.zip.

    In the meantime I'll try to fix the problem with the original link

  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by Fallon on Jan 26, 2010 05:32
    Thanks, that worked!
  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by Fallon on Jan 26, 2010 06:55

    Ok, I've had a chance to take a quick look at this app, and I'm quite impressed.

    The concept and execution of the code is very good, however, the fact that you married that to an aesthetic user interface, makes this a truly nice piece of work.

    Please let us hear more from you, and thanks for the code.  I might also suggest that you consider moving this to Codeplex, especially if you plan to enhance it further.

  • walterf

    RE: An Excel file Viewer in Silverlight 4


    posted by walterf on Jan 26, 2010 12:13
    Thanks a lot for the good words! Probably I will follow your suggestion.
    And... I know, I should translate my blog in english. It is just a matter of time.
  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by anonsvn on Jan 26, 2010 19:55
    You need a real Excel-like control in Silvelright, Check Syncfusion Silverlight Grid, http://www.syncfusion.com/products/user-interface-edition/silverlight/grid
  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by rmaclean on Jan 27, 2010 19:12
    Thanks for the mention of my blog :)
  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by kelvin on Feb 24, 2010 17:04
    error occur in IEnumerable<XElement> sharedStringsElements = from s in SharedStringsElement.Descendants(excelNamespace + "t") select s; when i add excel file to the box
  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by turab on Apr 24, 2010 02:35

    Drag and drop works but once you click on item on the tree there is an issue, essentially you end up invoking

     

     

    private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)

     

     

     

    I haveVS.NET RC 2010 Ultimate and Silivelight 4 RC installed.

  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by Vinod on May 14, 2010 12:00

    That nice one what i want, I need more in this like this screen shot http://h.imagehost.org/0008/excelview.gif, can I get help from you I am a designer i want to learn.

     

    thanks vinod

  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by chenkai on Jun 10, 2010 06:08

    nice work!

     

  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by KG on Jun 18, 2010 16:45
    I can't run the demo (compiled using an expired beta version)
  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by Anders on Aug 18, 2010 11:01

    Hi Mr. Ferrari,

    I've checked out the video of your excel viewer, and I am also quite impressed. Like KG said, the sample link doesn't work, since you used a beta version of Silverlight when making it. Probably of the same reason, the sample project fails to build because of missing assemblies.

  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by Walter on Aug 19, 2010 17:33

    Hi Anders,

    I've updated the source code with the references to SL4 SL Toolkit April 2010 libs. Download from here and rebuild the solution. It should work.

    Walter

  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by Robin on Sep 13, 2010 12:52
    Hi, I downloaded and ran the code but I can't drop any files on the left hand box as it doesn't allow me to. Incidentaly, the ExcelDataReader classes on codeplex do now allow you to convert excel files in Silverlight
  • -_-

    RE: An Excel file Viewer in Silverlight 4


    posted by Michael on Nov 30, 2010 19:02

    Would be nice if you can create a version to read Excel 2007 documents

  • -_-

    RE: An Excel file Viewer in Silverlight


    posted by Arati on Feb 23, 2011 18:29
    gud example in silverlight 4.0 but is there any control to upload excel files in silverlight application so that after hosting we can c this .xlsx file
  • -_-

    RE: An Excel file Viewer in Silverlight


    posted by Vinu on Apr 28, 2011 10:47
    Links for Excel Viewer movie not working fine.
  • iiordanov

    RE: An Excel file Viewer in Silverlight


    posted by iiordanov on Apr 28, 2011 10:50
    @Vinu - do you get an error or the video is not playing well?
  • CrikeyMoses

    Re: An Excel file Viewer in Silverlight


    posted by CrikeyMoses on Jul 12, 2011 13:33

    Very nice article!!

    I'm interested in two way binding using the MVVM pattern... I got pretty close but no luck in the end.
    Can you help?

    Thanks

  • -_-

    Re: An Excel file Viewer in Silverlight


    posted by on Aug 26, 2011 09:10
    Found new solution to create Excel and WORD document in silverlight app client WITHOUT MS Office installed,
    Excel in silverlight
    http://www.e-iceblue.com/Introduce/excel-for-net-introduce.html
    Word in silverlight
    http://www.e-iceblue.com/Introduce/word-for-net-introduce.html
    Hope help to everyone.
  • yoosufshanij

    Re: An Excel file Viewer in Silverlight


    posted by yoosufshanij on Aug 29, 2011 14:57
    Please advise me how to handle if excel have empty cells in between
  • vivek08

    Re: An Excel file Viewer in Silverlight


    posted by vivek08 on Sep 27, 2011 10:14

    Hello Sir,

    I am Vivek. I have download the code of this project. I got some errors...Error 'XLSXparsingLib.ExcelClass' does not implement interface member 'InteractChartCommonLib.IFileDropFormat.GetData(string)'. 'XLSXparsingLib.ExcelClass.GetData(string)' cannot implement 'InteractChartCommonLib.IFileDropFormat.GetData(string)' because it does not have the matching return type of 'System.Collections.Generic.IEnumerable<System.Collections.IDictionary>'. Please help to find the solution....Thanks & Regards Vivek.









  • Arterius

    Re: An Excel file Viewer in Silverlight


    posted by Arterius on Nov 16, 2011 10:33

    Doesn't work for me. Unable to drop .xlsx file.

  • MohanPL

    Re: An Excel file Viewer in Silverlight


    posted by MohanPL on Dec 02, 2011 09:44
    I have found an issue, when reading date from the xlsx file. Any solution for this, please let me know. ThanQ :)
  • StephenChen

    Re: An Excel file Viewer in Silverlight


    posted by StephenChen on Jan 03, 2012 10:47
    If any of you need an Excel component for .NET/Silverlight, you can come to the store of e-iceblue.com where you can get upto 25% OFF discount before 2012.01.10.
  • srhreza

    Re: An Excel file Viewer in Silverlight


    posted by srhreza on Feb 21, 2012 06:35

    Dear walterf 

    Thank you for your nice work and share it among all of us. This is a nice project but it wont work if the work sheet has a header or topic, I would like to a functionality of reading excel file from a specific row like row 5 and below and before 5 not be read. thanks 


  • srhreza

    Re: An Excel file Viewer in Silverlight


    posted by srhreza on Feb 21, 2012 06:37

    Dear walterf 

    Thank you for your nice work and share it among all of us. 

    This is a nice project but it wont work if the work sheet has a header or topic, I would like to a functionality of reading excel file

     from a specific row like row 5 and below and before 5 not be read. 

    thanks 

  • drkelly

    Re: An Excel file Viewer in Silverlight


    posted by drkelly on Mar 06, 2012 19:07

    Excellent work, this was very helpful, however I've found a few issues when dealing with big spreadsheets. Your code as it is only supports up to 26 columns (A..Z) when you go beyond, you overwrite the base (A..Z) again. I fixed this by changing the following line of GetData

    from:
    dict[cell.Attribute("r").Value.Substring(0, 1)] = cellValue as Object; to:
    dict[cell.Attribute("r").Value.Replace(row.Attribute("r").value,""] = cellValue as Object;

    This just removes the row number from the ColRow attribute of the cell, leaving only the Column.


    Also, I ran into an issue with some of my sharedString values being multi-line, which caused your parsing routine to return an incorrect index.

    If you change the following line of ParseSharedStrings() it will work correctly.

    From:              
    IEnumerable<XElement> sharedStringsElements = from s in SharedStringsElement.Descendants(excelNamespace + "t")
                                                                  select s;


    To:
    IEnumerable<XElement> sharedStringsElements = from s in SharedStringsElement.Descendants(excelNamespace + "si")
                                                                  select s;



    Thanks again for the great intro into reading excel files.


Add Comment

Login to comment:
  *      *