EWA Companion Part 2: Save As Functionality

In a previous post I discussed the EWA companion and how to set it up for saving back to SharePoint. This post will show the next set of capabilities which is the ability to Save As (actually, it exports or saves under another name - the new workbook will not be opened like Save-As usually works).

To set up Save As functionality, the web-page designer needs to check at least one of the Save As Options:

image

Note that you can choose what options you want to have - Workbook will allow the full workbook to be saved (though it requires full read permissions to the file). Snapshot and Published require less privileges, but do not contain information such as formulas and connections.

Once these are checked, the EWA companion shows up new functionality:

image 

Selecting one of these options un-hides some UI that will allow users to specify the name they want to save as:

image

The user can now type a name of a file, or click the "Browse" button for help with selecting the document library wanted:

image

Clicking on the "Save" button will now copy the current workbook as viewed in the EWA into the new file name.

The code

The code for working this is very similar to the code shown in the previous post - the code that saves to SharePoint and the code that gets the workbook was already shown there. The only mildly interesting part here is the code that is generated

First, the code that adds the Save panel to the HTML:

 

private void AddSaveAsButtons()

{

       m_saveAsContainer = new Panel();

       Controls.Add(m_saveAsContainer);

       m_saveAsContainer.Style.Add(HtmlTextWriterStyle.Display, "none");

       Label label = new Label();

       m_saveAsContainer.Controls.Add(label);

       label.Text = "Save As:";

       m_assetPicker = new AssetUrlSelector();

       m_saveAsContainer.Controls.Add(m_assetPicker);

       m_saveAsTypeTextBox = new TextBox();

       m_saveAsContainer.Controls.Add(m_saveAsTypeTextBox);

       m_saveAsTypeTextBox.Style.Add(HtmlTextWriterStyle.Display, "none");

       m_saveAsButton = new Button();

       m_saveAsContainer.Controls.Add(m_saveAsButton);

       m_saveAsButton.Text = "Save";

       m_saveAsButton.Click += new EventHandler(SaveAsButton_Click);

       string scriptlet = String.Format("if (!confirm('{0}')) return;",

              "If this file exists, it will be overwritten by the new file. Are you sure you want to proceed?");

       m_saveAsButton.OnClientClick = scriptlet;

       System.Web.UI.WebControls.MenuItem subMenu = new System.Web.UI.WebControls.MenuItem("Save As");

       m_menu.Items.Add(subMenu);

       if (ShowSaveAsFull)

       {

              AddSaveAsButton(subMenu, SaveAsFull, "Save Workbook");

       }

       if (ShowSaveAsSnapshot)

       {

              AddSaveAsButton(subMenu, SaveAsSnapshot, "Save Snapshot");

       }

       if (ShowSaveAsPublished)

       {

              AddSaveAsButton(subMenu, SaveAsPublished, "Save Published Items");

       }

}

 

The code adds a panel to the HTML, hides it and then fills it up with a label, an Asset Picker and a button. The button's OnClick event is hooked to the SaveAsButton_Click(). The function also adds menu items depending on what options were selected by the user by using the AddSaveAsButton() method:

 

private void AddSaveAsButton(System.Web.UI.WebControls.MenuItem subMenu, string type, string text)

{

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

       subMenu.ChildItems.Add(item);

       string scriptlet = String.Format(

              "javascript:document.getElementById('{0}').value = EwaGetSessionId('{1}'); document.getElementById('{2}').value = '{3}'; EcShowSaveAsDialog('{4}');",

              m_sessionIdTextBox.ClientID,

       ConnectedEwa.ClientID,

              m_saveAsTypeTextBox.ClientID,

              type,

              m_saveAsContainer.ClientID);

       item.NavigateUrl = scriptlet;

}

 

The code adds an event to each of the save-as buttons - depending on what the button is, it will set up a different type inside the input - that will determine how GetWorkbook() will be called later. The code also sets up the session id into the appropriate hidden field.

Here's what the Save event handler looks like:

 

void SaveAsButton_Click(object sender, EventArgs e)

{

       try

       {

              string typeString = m_saveAsTypeTextBox.Text;

              WorkbookType type = WorkbookType.FullWorkbook;

              if (typeString == SaveAsSnapshot)

              {

                     type = WorkbookType.FullSnapshot;

              }

              else if (typeString == SaveAsPublished)

              {

                     type = WorkbookType.PublishedItemsSnapshot;

              }

              byte[] bits = GetWorkbookBits(type);

              using (SPSite site = new SPSite(ConnectedEwa.WorkbookUri))

              using (SPWeb web = site.OpenWeb())

              {

                     SPFile file = web.GetFile(m_assetPicker.AssetUrl);

                     file.SaveBinary(bits);

                     SetMessage("Save succeeded!");

              }

       }

       catch (UserException u)

       {

              SetMessage("Save failed: " + u.ToString());

       }

       catch (Exception ex)

       {

              SetMessage("Unknown save failure:" + ex.ToString());

       }

}

 

The click event kicks off the following code:

void SaveAsButton_Click(object sender, EventArgs e)

{

       try

       {

              string typeString = m_saveAsTypeTextBox.Text;

              WorkbookType type = WorkbookType.FullWorkbook;

              if (typeString == SaveAsSnapshot)

              {

                     type = WorkbookType.FullSnapshot;

              }

              else if (typeString == SaveAsPublished)

              {

                     type = WorkbookType.PublishedItemsSnapshot;

              }

              byte[] bits = GetWorkbookBits(type);

              using (SPSite site = new SPSite(ConnectedEwa.WorkbookUri))

              using (SPWeb web = site.OpenWeb())

              {

                     SPFile file = web.GetFile(m_assetPicker.AssetUrl);

                     file.SaveBinary(bits);

                     SetMessage("Save succeeded!");

              }

       }

       catch (UserException u)

       {

              SetMessage("Save failed: " + u.ToString());

       }

       catch (Exception ex)

       {

              SetMessage("Unknown save failure:" + ex.ToString());

       }

}

 

As you can see, the code is very similar to the what the Save button does in the previous post. Instead of saving back though, it saves into an existing file.

The next post will discuss the Open menu item.