Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Улучшаем экспорт в Excel для SharePoint

Anna | 17.06.2014 | нет комментариев
Стандартная вероятность экспорта в Excel в SharePoint работает достаточно странным образом. При нажатии на кнопку экспорта SharePoint отдает файл запроса в особом формате, тот, что открывается Excel, и теснее сам Excel затягивает данные.

Преобладание такого подхода в том, что данные в Excel дозволено обновить, так как есть соединение. Но недостатков огромнее:

  • Необходим установленный Excel на компьютер, Дабы получить данные.
  • В полученном документе для наименований колонок применяется InternalName полей.
  • В полученном документе применяется “сырой” формат данных, что вдалеке не неизменно подходит.

С поддержкой небольшого объема кода дозволено подменить стандартную функцию экспорта на свою так, что пользователи ничего не подметят.

Подмена кнопок экспорта

Дабы заменить присутствующий элемент в Ribbon нужно добавить новейший CommandUIDefinition с параметром Location равным Id присутствующего элемента. Все типовые элементы находятся в файлеC:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\<b>14</b>\TEMPLATE\GLOBAL\XML\CMDUI.XML для SharePoint 2010 (либо 15 для SharePoint 2013).

Для того, Дабы подменить кнопки экспорта в Excel нужно обнаружить кнопки с Id равнымиRibbon.List.Actions.ExportToSpreadsheet и Ribbon.Library.Actions.ExportToSpreadsheet и всецело скопировать в свой план. В качестве Location для новых элементов нужно указать эти Id.

Много копипасты

<CommandUIDefinitions>
  <CommandUIDefinition
    Location="Ribbon.Library.Actions.ExportToSpreadsheet">
    <Button Id="Ribbon.Library.Actions.ExportToSpreadsheet-Replacement"
      Sequence="40"
      Command="ExportToSpreadsheet-Replacement"      
      Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-152" Image16by16Left="-32"
      Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-352" Image32by32Left="0"
      LabelText="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipTitle="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipDescription="$Resources:core,cui_STT_ButExportListToSpreadsheet;"
      TemplateAlias="o2"
        />
  </CommandUIDefinition>
  <CommandUIDefinition
    Location="Ribbon.List.Actions.ExportToSpreadsheet">
    <Button Id="Ribbon.List.Actions.ExportToSpreadsheet-Replacement"
      Sequence="40"
      Command="ExportToSpreadsheet-Replacement"
      Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-152" Image16by16Left="-32"
      Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-352" Image32by32Left="0"
      LabelText="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipTitle="$Resources:core,cui_ButExportToSpreadsheet;"
      ToolTipDescription="$Resources:core,cui_STT_ButExportListToSpreadsheet;"
      TemplateAlias="o1"
        />
  </CommandUIDefinition>
</CommandUIDefinitions>

Есть еще отдельная кнопка для календаря с Id="Ribbon.Calendar.Calendar.Actions.ExportToSpreadsheet", с ней дозволено сделать тоже самое.

Создание контрола

Кнопка должна вызывать определенный серверный код. Дабы поведение было подобно стандартной кнопке, отменнее каждого сделать DelegateControl, тот, что будет размещаться на всякой странице. Для этого есть контейнер с Id="AdditionalPageHead":

<Control 
  Id="AdditionalPageHead"
  Sequence="1000"
  ControlAssembly="$SharePoint.Project.AssemblyFullName$" 
  ControlClass="$SharePoint.Type.7fd7c6f0-4eda-48ce-ac8f-aa9f9d2666ac.FullName$"/>

Кастомная кнопка будет вызывать PostBack, обрабатываемый нашим контролом. Кнопка может быть нажата на странице представления списка, тогда не нужно передавать дополнительных параметров. Также представления списков могут быть добавлены на обыкновенные страницы как веб-части, тогда необходимо передать Id списка и представления на сервер.

Увы, приобретение Id представления, в котором была нажата кнопка – нетривиальная задача. Следственно я ограничусь только передачей Id списка.

<CommandUIHandlers>
  <CommandUIHandler
    Command="ExportToSpreadsheet-Replacement"
    CommandAction="javascript:(function(){var x=SP.ListOperation.Selection.getSelectedList(); if (x) {__doPostBack('ExportToSpreadsheet-Replacement', x);}})();" />
</CommandUIHandlers>

Дальше на сервере необходимо проверить нажата ли кнопка на странице представления списка либо на обыкновенной странице:

protected override void OnLoad(EventArgs e) { 
    if (this.Page.Request["__EVENTTARGET"] == "ExportToSpreadsheet-Replacement") 
    {
        var spContext  = SPContext.Current;
        SPList list;
        SPView view;

        if (spContext.ViewContext.View != null)
        {
            list = spContext.List;
            view = spContext.ViewContext.View;
        }
        else
        {
            var listId = new Guid(this.Page.Request["__EVENTARGUMENT"]);
            var web = spContext.Web;
            list = web.Lists[listId];
            view = list.DefaultView;
        }

        ExportData(list.Title   " - "   view.Title, GetDataTable(list, view));
    } 
}

Приобретение таблицы данных по представлению дюже легко:

private static System.Data.DataTable GetDataTable(SPList list, SPView view)
{
    var query = new SPQuery(view);
    SPListItemCollectionPosition position;
    var flags = SPListGetDataTableOptions.UseBooleanDataType | SPListGetDataTableOptions.UseCalculatedDataType;
    var result = list.GetDataTable(query, flags, out position);
    while (position != null)
    {
        list.AppendDataTable(query, flags, result, out position);
    }
    return result;
}

Генерация Excel файла

Последним шагом требуется сформировать Excel файл и отдать его заказчику. Один из самых примитивных методов сгенерировать Excel – применять библиотеку ClosedXml (http://closedxml.codeplex.com/).

private void ExportData(string title, System.Data.DataTable table)
{
    var wb = new XLWorkbook();
    var ws = wb.Worksheets.Add(title);
    ws.Cell(1, 1).InsertTable(table);

    var response = this.Page.Response;
    response.Clear();

    response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    var filename = title ".xlsx";
    response.AddHeader("content-disposition", GetContentDisposition(filename));

    // Flush the workbook to the Response.OutputStream
    using (var memoryStream = new MemoryStream())
    {
        wb.SaveAs(memoryStream);
        memoryStream.WriteTo(response.OutputStream);
    }
    response.End();
}

Первые три строки способа собственно формируют Excel документ (спасибо ClosedXml), а все остальное – код для отдачи файла заказчику.

Заголовок результата content-disposition дюже по-различному понимается различными браузерами, следственно отдать файл с правильным русским именем требует некоторых танцев с бубном.

Код для образования правильного заголовка content-disposition я обнаружил на StackOverflowstackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http

private string GetContentDisposition(string filename)
{
    var request = this.Page.Request;
    string contentDisposition;

    if (request.Browser.Browser == "IE" && (request.Browser.Version == "7.0" || request.Browser.Version == "8.0"))
        contentDisposition = "attachment; filename="   Uri.EscapeDataString(filename);
    else if (request.UserAgent != null && request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android)
        contentDisposition = "attachment; filename=\""   MakeAndroidSafeFileName(filename)   "\"";
    else
        contentDisposition = "attachment; filename=\""   filename   "\"; filename*=UTF-8''"   Uri.EscapeDataString(filename);
    return contentDisposition;
}

private static readonly Dictionary<char, char> AndroidAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._- ,@спользовать подобный подход в любом плане на ASP.NET.

 

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB