EWA Companion Part 3: Open/Download functionality

In the first part of this post series I showed the EWA companion and its various capabilities. In this part, I will delve deeper into the "Open" functionality of the EWA Companion web-part.

There are a few reasons behind adding the Open command to the EWA. While the functionality already seemingly exists in it (You can use the "Open" menu on EWA to open the active session inside Excel 2007), but some things are missing. For one, the "Open" menu only works with Excel 2007. If you have Excel 2003 or below installed with the compatibility pack, you will not be able to use that functionality. Another thing that is impossible to do today is to immediately Save As the workbook (you need to go to Excel 2007, and then choose Save As from there). Lastly, I have heard some users request printing functionality. While printing from the browser never really works that well, Microsoft does distribute a free Excel Viewer. Using this functionality, it should be possible to view and print Excel files without needing to install Excel on the client (of course, your functionality will be very diminished, but at least you should be able to print/view files outside of the browser).

To enable the Open feature, you need to go to the properties of the web-part and add them:

image

Once enabled, you will see the following menu item in the web-part:

image

Once clicked, you will get the regular IE/Firefox download dialog box:

image

This can then be used for whatever you want - clicking "Open" will run the default app (Excel 2003 for example). Clicking "Save" will give the save dialog.

The Code

There are 2 parts for the code for this portion of the companion. The first one is the ASPX page that actually allows you to get the file from the server and the second is the EWA companion code that invokes that page.

First, take a look at the ASPX page code-behind - the Load functionality:

protected override void OnLoad(EventArgs e)

{

       base.OnLoad(e);

       try

       {

              m_sessionId = Request.QueryString[SessionIdParam];

              string wt = Request.QueryString[WorkbookTypeParam];

              if (wt.Equals(WorkbookTypeFull, StringComparison.OrdinalIgnoreCase))

              {

                     m_workbookType = WorkbookType.FullWorkbook;

              }

              else if (wt.Equals(WorkbookTypeSnap, StringComparison.OrdinalIgnoreCase))

              {

                     m_workbookType = WorkbookType.FullSnapshot;

              }

              else if (wt.Equals(WorkbookTypePublished, StringComparison.OrdinalIgnoreCase))

              {

                     m_workbookType = WorkbookType.PublishedItemsSnapshot;

              }

       }

       catch (Exception ex)

       {

              m_error = ex;

       }

}

In here, the code simply takes the parameters and determines what the operation that needs to be done is. The actual code that streams the workbook back to the user is in the Render override:

protected override void Render(HtmlTextWriter writer)

{

       if (m_error != null)

       {

              writer.WriteLine(m_error.ToString());

              return;

       }

       try

       {

              ExcelService s = new ExcelService();

              Status[] status;

              byte[] bits = s.GetWorkbook(SessionId, WorkbookType, out status);

              Response.Clear();

              Response.AddHeader("LAST-MODIFIED", DateTime.Now.ToString("r"));

              Response.Charset = "";

              Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

              Response.OutputStream.Write(bits, 0, bits.Length);

              Response.OutputStream.Flush();

       }

       catch (Exception ex)

       {

              writer.WriteLine(ex.ToString());

       }

       Response.End();

}

 

The main part here is the GetWorkbook() call which takes the binary representation of the workbook. The second part is stuffing the file into the Response and making sure that it will get opened by the appropriate application on the client (that's what the ContentType property governs).

Finally, the companion invokes this page by using client-script. Here is the piece of code that gets attached to each of the "Open" menu items:

private void AddOpenButton(string text, string type, System.Web.UI.WebControls.MenuItem sub)

{

       System.Web.UI.WebControls.MenuItem item = new System.Web.UI.WebControls.MenuItem(text);

       sub.ChildItems.Add(item);

       item.NavigateUrl = String.Format(

                     "javascript:EcOpenExcelWorkbook('{0}','{1}');",

                     ConnectedEwa.ClientID,

                     type);

}

All this does is call the JavaScript function EcOpenExcelWorkbook(). That's defined inside the EwaCompanionScripts.js file:

function EcOpenExcelWorkbook(wpid, type)

{

       var sessionId = EwaGetSessionId(wpid);

       if (sessionId == null)

       {

              return 0;

       }

      

      

       window.location.assign("/_layouts/EcDownloadWorkbook.aspx?sid=" + encodeURIComponent(sessionId) + "&type=" + type);

}

All THIS function does, is get the session id inside the EWA and passes it to the EcDownloadWorkbook.aspx page for processing.

The next part of this series will discuss the last feature in the companion (at this time) which is the periodic refresh.