【问题标题】:Easiest way of porting html table data to readable document将 html 表格数据移植到可读文档的最简单方法
【发布时间】:2011-09-12 07:26:02
【问题描述】:

好的,

在过去的 6 个月里,我一直在努力构建一个系统,该系统允许用户以大文本区域的形式输入(支持大量表格、列表等)。几乎使用户能够像输入单词一样输入数据。但是,当我想导出所有这些数据时,我找不到可行的解决方案......

我的第一步是尝试找到一个支持来自数据源的原始 HTML 并将其呈现为普通 html 的报告软件,除了保持在一起的功能很糟糕,要么数据被分成两半(表格,列表等)我不想要。或者报告总是跳到下一页以避免这种情况,最终文档中有 15 个以上的空白页。

所以我正在寻找某种提示/方向,以了解将我的数据导出为可读文档(pdf 或 word pref)的最佳解决方案。

我得到的是以下数据细分,其中数据通常是原始 html。

-时期

--单位

---组

----问题

-----数据

最好的选择是什么?试图将 html 呈现为 pdf 或 rtf?我需要提示:(

而且有时数据长达 2-3 页,包含混合表格列表和纯文本。

【问题讨论】:

    标签: asp.net-mvc pdf ms-word reporting


    【解决方案1】:

    我建议您尝试将其保留在浏览器中,并在 HTML 中添加 print stylesheet 以使其在屏幕上以一种方式呈现,而 another way on paper。将打印样式表添加到您的 HTML 就像这样简单:

    <link rel="stylesheet" media="print" href="print.css">
    

    您应该能够使用 Html Agility Pack 之类的内容解析输入并将其(即使用 XSLT)转换为您想要的任何输出格式。

    另一种选择是将 HTML 写入浏览器,但将 Content-Type 设置为 Microsoft Word 特定的变体(有几个可供选择,具体取决于您所针对的 Word 版本)应该让浏览器询问如果用户想用 Microsoft Word 打开页面。在 Word 2007 和更新版本中,您还可以直接编写 Office Open XML Word,因为它是基于 XML 的。

    您可以使用的内容类型是:

    application/msword
    

    适用于二进制 Microsoft Word 文件,但也适用于 HTML。

    application/vnd.openxmlformats-officedocument.wordprocessingml.document
    

    适用于 Word 2007 及更高版本的较新的“Office Open XML”格式。

    【讨论】:

    • 我使用的是 TinyMCE,但问题不是输入。当我导出数据时,它会在数据上得到正确的布局。由于它的原始 html 我无法在渲染方法中手动添加分页符等(或者我可以?)。就像这样假设我的数据是 60% 的原始文本和 40% 的表格(里面有文本)。数据总长度为 3 页。如何(在渲染时)使数据出现,以便表格不会在分页符处被剪切。这就是我所要求的。将标题传递给单词并不是问题,是单词在其布局中必须是可以接受的!
    • 听起来像您在问的问题,是“我如何创作 Office Open XML 或二进制 Word 文档?”,阅读 MSDN 上的文档将有助于回答。无论哪种方式,使用 Html Agility Pack 解析输入将为您提供一个不错的文档对象模型 (DOM),您可以将其转换为您想要的任何内容,无论是 PDF 文档、另一个 HTML 表示形式、Microsoft Word 还是其他任何东西。请查看我更新的答案重新打印样式表,我认为这就是您所追求的。
    • 谢谢,我会调查的。
    • 你选择了打印样式表路由吗?
    【解决方案2】:

    您可以使用的解决方案是使用 System.Diagnostics.Process 在服务器上运行应用程序,该应用程序将转换站点并将其保存为 PDF 文档。

    您可以使用wkhtmltopdf,这是一个可以将 HTML 转换为 PDF 或图像的开源控制台程序。

    windows的安装程序可以从wkhtmltox-0.10.0_rc2 Windows Installer (i368)获取。

    安装 wkhtmltopdf 后,您可以复制解决方案内安装文件夹中的文件。您可以在解决方案中使用这样的设置:

    转换后的 pdf 将保存到 pdf 文件夹中。

    这是进行转换的代码:

    var wkhtmltopdfLocation = Server.MapPath("~/wkhtmltopdf/") + "wkhtmltopdf.exe";
    var htmlUrl = @"http://stackoverflow.com/q/7384558/750216";
    var pdfSaveLocation = "\"" + Server.MapPath("~/wkhtmltopdf/pdf/") + "question.pdf\"";
    
    var process = new Process();
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.FileName = wkhtmltopdfLocation;
    process.StartInfo.Arguments = htmlUrl + " " + pdfSaveLocation;
    process.Start();
    process.WaitForExit();
    

    htmlUrl 是您需要转换为 pdf 的页面的位置。它设置为此stackoverflow页面。 :)

    【讨论】:

    • 我正在尝试测试您的解决方案,如果它有效,对我有很大帮助..我不确定我是否完全理解它,但我想将我的 .aspx 转换为图像而不是 url,有可能以同样的方式吗?我也将服务器端的代码添加到我的 .ashx 中,但它似乎无法识别 new Process() !这是它应该工作的方式吗?
    • @astrocybernaute:代码有效,我在发布之前对其进行了测试,因为如果可能的话,我很感兴趣。它无法识别 Process() 可能是因为您尚未导入 System.Diagnostics,要使其正常工作,请添加“使用 System.Diagnostics;”
    • 我已添加 System.Diagnostics.Process,必须删除进程,现在识别它 :)thx。我可以用 var htmlUrl = "chartImage.aspx"; 替换网址怎么样
    • 我的意思是var htmlUrl = HttpContext.Current.Server.MapPath("~/chartImage.aspx");
    • @astrocybernaute:是的,只要它是一个有效的地址就可以工作
    【解决方案3】:

    这是一个普遍的问题,但有两件事会浮现在脑海中:访客模式和更改 Mime 类型。

    访客模式 您可以有两种单独的渲染技术。这取决于您的实施。

    MIME 类型 当请求发出时,在响应等中写出日期

    HttpContext.Current.Response.Clear();
    HttpContext.Current.Response.Charset = "utf-16";
    HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
    HttpContext.Current.Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.doc", filename));
    HttpContext.Current.Response.ContentType = "application/msword";
    HttpContext.Current.Response.Write("-Period");
    HttpContext.Current.Response.Write("/n");
    HttpContext.Current.Response.Write("--Unit");
    HttpContext.Current.Response.Write("/n");
    HttpContext.Current.Response.Write("---Group");
    HttpContext.Current.Response.Write("/n");
    HttpContext.Current.Response.Write("----Question");
    HttpContext.Current.Response.Write("/n");
    HttpContext.Current.Response.Write("-----Data");
    HttpContext.Current.Response.Write("/n");
    HttpContext.Current.Response.End();
    

    【讨论】:

    • 如果数据是 3 页,我将无法控制何时何地执行分页。 IE 我不希望表格、列表等在分页符中被剪切。 (所以我希望有逻辑来检查数据是否适合剩余空间,否则进行分页)。
    • 嗯,据我所知,您将面临各种各样的这些问题。你不能用其他东西等报告服务来呈现信息吗? HTML 确实是为在 Web 浏览器中显示而设计的。
    • 我尝试使用 Devexpress(它是唯一支持 HTML 的报告软件)。我们需要使用 html,因为用户必须能够为他们的答案创建表格和列表。这就是让它如此复杂的原因......
    • 他们是否与信息交互?确定 Word 和 PDF 只是用于单向渲染?当我尝试打印一些网页时,我只是从以前的经验中知道......这是浪费时间。最终,我们强迫用户使用 Reporting Services 来打印他们想要打印的任何内容。
    • 系统基本上是一个报告页面,管理员提问和用户回答(在表格和列表中)。然后用户可以打印所有问题和答案的文档并显示给其他人。而这份文件就是出问题的地方。由于所有的硬 HTML,它的格式很糟糕。而且我不知道如何在没有人手的情况下正确格式化它。很少有报告服务提供 HTML 支持,我开始弄清楚为什么,它似乎很难使用:(
    【解决方案4】:

    这是另一种选择,使用打印屏幕(虽然它不负责滚动,但我认为您应该能够构建它)。此示例可以扩展以满足您的业务需求,尽管它是一种 hack。你传给它一个 URL,它会生成一张图片。

    这样称呼

     protected void Page_Load(object sender, EventArgs e)
                {
                    int screenWidth = Convert.ToInt32(Request["ScreenWidth"]);
                    int screenHeight = Convert.ToInt32(Request["ScreenHeight"]);
                    string url =        Request["Url"].ToString();
                    string bitmapName = Request["BitmapName"].ToString();
    
    
                WebURLToImage webUrlToImage = new WebURLToImage()
                {
                    Url = url,
                    BrowserHeight = screenHeight,
                    BrowserWidth = screenWidth,
                    ImageHeight = 0,
                    ImageWidth = 0
                };
    
            webUrlToImage.GenerateBitmapForUrl();
            webUrlToImage.GeneratedImage.Save(Server.MapPath("~") + @"Images\" +bitmapName + ".bmp");
        }
    

    从网页生成图像。

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Threading;
    using System.IO;
    
    public class WebURLToImage
    {
        public string Url { get; set; }
        public Bitmap GeneratedImage { get; private set; }
        public int ImageWidth { get; set; }
        public int ImageHeight { get; set; }
        public int BrowserWidth { get; set; }
        public int BrowserHeight { get; set; }
    
        public Bitmap GenerateBitmapForUrl()
        {
            ThreadStart threadStart = new ThreadStart(ImageGenerator);
            Thread thread = new Thread(threadStart);
    
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            thread.Join();
            return GeneratedImage;
        }
    
        private void ImageGenerator()
        {
            WebBrowser webBrowser = new WebBrowser();
            webBrowser.ScrollBarsEnabled = false;
            webBrowser.Navigate(Url);
    
            webBrowser.DocumentCompleted += new
    WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
    
            while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
                Application.DoEvents();
            webBrowser.Dispose();
        }
    
        void webBrowser_DocumentCompleted(object sender,
    WebBrowserDocumentCompletedEventArgs e)
        {
            WebBrowser webBrowser = (WebBrowser)sender;
            webBrowser.ClientSize = new Size(BrowserWidth, this.BrowserHeight);
            webBrowser.ScrollBarsEnabled = false;
            GeneratedImage = new Bitmap(webBrowser.Bounds.Width, webBrowser.Bounds.Height);
            webBrowser.BringToFront();
    
            webBrowser.DrawToBitmap(GeneratedImage, webBrowser.Bounds);
    
            if (ImageHeight != 0 && ImageWidth != 0)
                GeneratedImage =
    (Bitmap)GeneratedImage.GetThumbnailImage(ImageWidth, ImageHeight,
    null, IntPtr.Zero);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 2010-12-01
      • 1970-01-01
      相关资源
      最近更新 更多