Spreadsheet to Accessible PDF

Use the Spreadsheet Document API to export a document to a tagged (accessible) PDF file. Click Select File and load a document in XLSX, XLSB, XLS, XLSM, XLTX, XLTM, XLT, or XML format. Select an output format from the list and click Download to save the result. The maximum file size you can upload is 1MB.

)
Convert file to:
@model AspNetCoreDemos.OfficeFileAPI.SpreadsheetAccessiblePDFModel
@using DevExtreme.AspNet.Mvc

@using (Html.BeginForm("SpreadsheetAccessiblePDFExportTo", "DocumentConversion", FormMethod.Post)) {
    @Html.HiddenFor(model => model.DocumentUrl)
    <script type="text/javascript">
        function fileUploader_valueChanged(e) {
            var files = e.value;
            if (files.length > 0) {
                $("#selected-files .selected-item").remove();

                $.each(files, function (i, file) {
                    var $selectedItem = $("<div />").addClass("selected-item");
                    $selectedItem.append(file.name);
                    $selectedItem.appendTo($("#selected-files"));
                });

                $("#selected-files").show();

                $('#DocumentUrl').val(files[0].name);
                var button = $("#downloadButton").dxButton("instance");
                button.option("disabled", false);
            }
            else
                $("#selected-files").hide();
        }
        function UpdatePreview() {
            SpreadsheetPreview.Update("");
        }
        function DownloadClick() {
            document.getElementById("error").hidden = true;
        }
    </script>


    <div class="uploader-panel">
        @(Html.DevExtreme().FileUploader()
                           .ID("file-uploader")
                           .Name("myFile")
                           .Multiple(false)
                           .ShowFileList(true)
                           .Accept(".xlsx, .xlsm, .xlsb, .xls, .xltx, .xltm, .xlt, .xml")
                           .MaxFileSize(1048576)
                           .UploadMode(FileUploadMode.Instantly)
                           .UploadUrl(Url.Action("DocumentUpload", "SpreadsheetAccessiblePDF"))
                           .OnValueChanged("fileUploader_valueChanged")
                           .OnFilesUploaded("UpdatePreview"))
        )
    </div>
    <div class="document-downloader" style="margin-bottom:10px">
        <div class="document-downloader-item">Convert file to:</div>
        <div class="document-downloader-format-selector">
            @(Html.DevExtreme().SelectBoxFor(m => m.PdfCompatibility)
                       .DataSource(new object[]
                                { new { Text = "PDF/A-1a", Value = "pdf/a-1a" },
                                    new { Text = "PDF/A-2a", Value = "pdf/a-2a" },
                                    new { Text = "PDF/A-3a", Value = "pdf/a-3a" },
                                    new { Text = "PDF/UA", Value = "pdf/ua" } })
                       .ValueExpr("Value")
                       .DisplayExpr("Text"))
        </div>
        <div class="document-downloader-item">
            @(Html.DevExtreme().Button()
                               .ID("downloadButton")
                               .Text("Download")
                               .Disabled(false)
                               .Type(ButtonType.Default)
                               .StylingMode(ButtonStylingMode.Contained)
                               .UseSubmitBehavior(true)
                               .OnClick("DownloadClick"))
        </div>
        <div id="error" class="error-message-right">
            <span>@ViewBag.ErrorMessage</span>
        </div>
    </div>
    <div class="demo-view-container" style="width:100%;box-sizing:border-box">
        @await Html.PartialAsync("SpreadsheetPreviewPartial", Model.PreviewModel)
    </div>
}

@model AspNetCoreDemos.OfficeFileAPI.SpreadsheetPreviewModel

<iframe id="previewFrame" src="@Url.Action(Model.PreviewDocumentAction, Model.ControllerName)" class="demo-preview-border" style="width: 100%; height: @Model.HeightInPixels;box-sizing:border-box"></iframe>

<script type="text/javascript">
    SpreadsheetPreview = {
        basePath: '@Url.Action(Model.PreviewDocumentAction, Model.ControllerName)',
        Update: function (param) {
            var iframeElementName = "previewFrame";
            var iframeElement = document.getElementById(iframeElementName);
            if (!iframeElement)
                return;
            var additionalParams = "&" + new Date().valueOf();
            if (param)
                additionalParams = param;
            iframeElement.src = this.basePath + "?" + additionalParams;
        }
    };
</script>

using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;

namespace AspNetCoreDemos.OfficeFileAPI {
    public partial class DocumentConversionController : DocumentProcessingController {
        public DocumentConversionController(ILogger<DocumentConversionController> logger, IWebHostEnvironment hostingEnvironment)
            : base(logger, hostingEnvironment) {
        }

        protected const string LoadDocumentExceptionString = "ERROR: Cannot convert this document.";
        protected override string SessionKey => throw new NotImplementedException();
    }
}
using System;
using System.IO;
using DevExpress.Spreadsheet;
using DevExpress.XtraPrinting;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace AspNetCoreDemos.OfficeFileAPI {
    public class SpreadsheetAccessiblePDFController : DocumentConversionController {
        public SpreadsheetAccessiblePDFController(ILogger<SpreadsheetAccessiblePDFController> logger, IWebHostEnvironment hostingEnvironment)
            : base(logger, hostingEnvironment) {
        }
        public static string SpreadsheetSessionKey => "SpreadsheetAccessiblePDFFileKey";
        protected override string SessionKey => SpreadsheetSessionKey;
    }

    public partial class DocumentConversionController {
        public IActionResult SpreadsheetAccessiblePDF() {
            SpreadsheetAccessiblePDFModel model = new SpreadsheetAccessiblePDFModel();
            return View(model);
        }
        public IActionResult SpreadsheetAccessiblePDFPreview(SpreadsheetAccessiblePDFModel model) {
            SpreadsheetPreviewModel previewModel = new SpreadsheetPreviewModel();
            previewModel.Workbook = CreateWorkbookAndLoadDocument(model);
            return GenerateHtmlPreview(previewModel);
        }
        [HttpPost]
        public IActionResult SpreadsheetAccessiblePDFExportTo(SpreadsheetAccessiblePDFModel model) {
            try {
                Workbook workbook = CreateWorkbookAndLoadDocument(model);
                MemoryStream stream = new MemoryStream();
                SpreadsheetFileFormat documentType = SpreadsheetFileFormat.Pdf;
                string format = model.PdfCompatibility;
                PdfExportOptions exportOptions = new PdfExportOptions();
                if(format == "pdf/a-1a") {
                    exportOptions.PdfACompatibility = PdfACompatibility.PdfA1a;
                } else if(format == "pdf/a-2a") {
                    exportOptions.PdfACompatibility = PdfACompatibility.PdfA2a;
                } else if(format == "pdf/a-3a") {
                    exportOptions.PdfACompatibility = PdfACompatibility.PdfA3a;
                } else if(format == "pdf/ua") {
                    exportOptions.PdfUACompatibility = PdfUACompatibility.PdfUA1;
                }
                exportOptions.ConvertImagesToJpeg = false;
                workbook.ExportToPdf(stream, exportOptions);

                string contentType = SpreadsheetUtils.ConvertToContentType(documentType);
                string fileExtension = SpreadsheetUtils.ConvertToFileExtension(documentType);
                string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(Uri.UnescapeDataString(model.DocumentUrl));
                return CreateFileStreamResult(stream, contentType, fileExtension, fileNameWithoutExtension);
            } catch(Exception ex) {
                Logger.LogError(ex, LoadDocumentExceptionString);
                ViewBag.ErrorMessage = LoadDocumentExceptionString;
                return View(model);
            }
        }
        Stream CreateDocumentStream(SpreadsheetAccessiblePDFModel model, DocumentFormat documentFormat) {
            if(documentFormat == DocumentFormat.Undefined)
                return null;
            Workbook workbook = CreateWorkbookAndLoadDocument(model);
            MemoryStream result = new MemoryStream();
            workbook.SaveDocument(result, documentFormat);
            result.Seek(0, SeekOrigin.Begin);
            return result;
        }
        Workbook CreateWorkbookAndLoadDocument(SpreadsheetAccessiblePDFModel model) {
            Workbook workbook = new Workbook();
            try {
                byte[] data;
                if(HttpContext.Session.TryGetValue(SpreadsheetAccessiblePDFController.SpreadsheetSessionKey, out data))
                    workbook.LoadDocument(data);
                else {
                    string filePath = HostingEnvironment.ContentRootPath + model.DocumentUrl;
                    workbook.LoadDocument(filePath);
                }
            } catch(Exception ex) {
                Logger.LogError(ex, LoadDocumentExceptionString);
                ViewBag.ErrorMessage = LoadDocumentExceptionString;
            }
            return workbook;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace AspNetCoreDemos.OfficeFileAPI {
    public class SpreadsheetAccessiblePDFModel : SpreadsheetModelBase {
        public SpreadsheetAccessiblePDFModel() {
            PreviewModel.PreviewDocumentAction = "SpreadsheetAccessiblePDFPreview";
            PreviewModel.ControllerName = "DocumentConversion";
            DocumentUrl = "/Documents/BreakevenAnalysis.xlsx";
            FileFormat = SpreadsheetFileFormat.Xlsx;
            PdfCompatibility = "pdf/a-3a";
        }

        public string PdfCompatibility { get; set; }
        public string DocumentUrl { get; set; }
    }
}
namespace AspNetCoreDemos.OfficeFileAPI {
    public class SpreadsheetModelBase {
        public SpreadsheetModelBase() {
            PreviewModel = new SpreadsheetPreviewModel();
            PreviewModel.OwnerPropertyName = "PreviewModel";
            FileFormat = SpreadsheetFileFormat.Xlsx;
        }

        public SpreadsheetFileFormat FileFormat { get; set; }
        public SpreadsheetPreviewModel PreviewModel { get; internal set; }
    }
}