代码之家  ›  专栏  ›  技术社区  ›  funwithcoding

基于数据库查询的Silverlight服务器端Excel报表生成

  •  2
  • funwithcoding  · 技术社区  · 14 年前

    我正在使用Silverlight3构建一个内部网应用程序。在其中一个页面上,我需要生成一个Excel报告。用户可以通过用户界面选择一些参数并点击提交按钮,然后Silverlight将生成一个Excel报告并弹出一个窗口,允许用户保存生成的报告。

    有没有简单而直接的方法来实现这一点?

    下面是我可以想到但仍然不完全清楚如何处理这个问题的步骤。

    1. 用户选择几个组合框,然后选择列表框
    2. 用户点击提交按钮
    3. btnSubmit_Click(提交按钮单击事件处理程序)将调用“takeQueryParamsaSync”wcf服务调用
    4. 服务器端的WCF服务创建动态SQL查询并执行查询并获取数据
    5. Silverlight客户端通过调用回调函数“takeQueryParamsaSync-completed”收到获取数据完成的通知。

    现在,Silverlight客户端如何请求从服务器生成报告,以及如何将生成的报告提供给用户?它是否必须调用“takequeryparamsasync-completed”回调函数中的另一个wcf服务来从提取的数据请求报告文件?如果是这样,WCF服务将如何记住,使用这些特定的查询参数从DB获取数据的是同一个客户机?我必须在WCF服务和Silverlight之间保持状态吗?没有更简单的解决方案吗?

    客户端Excel报告生成不是一个选项(因为生成的Excel文件应包含Excel图表)。真的那么难吗?或者我只是过于简单化自己,不知道如何实现它?

    任何指针或代码示例都是很好的。谢谢您。

    我相信应该有一个优雅的解决方案。

    2 回复  |  直到 14 年前
        1
  •  1
  •   DaveB    14 年前

    如果您有可用的ASP.NET,可以创建一个HTTP处理程序,您可以使用Silverlight中的HTML桥来调用该处理程序,该桥将把您的报表参数作为查询字符串。然后生成报告并将其发送回客户机。

    string printUrl = string.Format("createxlsreport.ashx?param1={0}", param1);
    HtmlPage.Window.Navigate(new Uri(printUrl, UriKind.Relative), "_blank", "toolbar=yes,location=no,status=no,menubar=no,resizable=yes");
    

    将文件发送回客户端:

    private void SendFileToClient(byte[] file, string fileName)
    {
        HttpResponse Response = HttpContext.Current.Response;
        Response.Clear();
        Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", fileName));
        // Add a HTTP header to the output stream that contains the 
        // content length(File Size). This lets the browser know how much data is being transfered
        Response.AddHeader("Content-Length", file.Length.ToString());
        // Set the HTTP MIME type of the output stream
        Response.ContentType = "application/vnd.ms-excel";
        // Write the data out to the client.
        Response.BinaryWrite(file);
        Response.End();
    }
    
        2
  •  1
  •   Johannes    14 年前

    好吧,我有一些想法:

    你要用Silverlight吗 SaveDialog 下载文件?首先,我认为您知道这一点,它是使用Silverlight3将文件保存到用户计算机的唯一方法。 如果要使用该方法,则需要用户驱动的事件来保存文件(即单击按钮)。

    所以是的,你必须去接那个额外的电话,但不能从内部 takeQueryParamsAsync_Completed 代码。您所能做的就是激活一个按钮或其他一些东西,它将通知用户报告已生成,并让他们单击 download 按钮。不过,还有其他选项,我最近实现了一个下载选项,它利用URL重定向到服务器上的文件URL,并使我能够解决整个问题(没有默认的文件名选项,不能只打开文件,但必须先将其保存到HDD等)。

    关于国家事务的问题。这实际上取决于您将生成的报告存储在哪里。您是将它存储在硬盘上、数据库中,还是保存在内存中?这将影响您如何调用文件。一种简单的方法是将密钥返回到客户机,然后作为链接到文件的密钥返回到服务器。这样就不必在WCF服务和Silverlight之间维护状态。

    编辑 嗯,在WCF服务方面,您需要额外的服务。 我的看起来像

    <service behaviorConfiguration="NewBehavior" name="ALMWCFHost.FileProvider.FileService">
       <endpoint address="" behaviorConfiguration="NewBehavior1" binding="webHttpBinding"
          bindingConfiguration="" name="File" contract="ALMWCFHost.FileProvider.IFileService" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8021/Files/" />
          </baseAddresses>
        </host>
      </service>
    

    您还必须创建一个新的端点行为

    <endpointBehaviors>
    <behavior name="NewBehavior1">
        <webHttp />
    </behavior></endpointBehaviors>
    

    这将创建一个WebHTTP服务。

    现在,您将创建一些端点:

    [OperationContract, WebGet(UriTemplate = "GetFile/{filename}")]
    
        Stream GetFile(string filename);
    
        [OperationContract, WebGet]
        Stream GetYCFile(string date, string type, string format);
    
        [OperationContract, WebGet(UriTemplate = "GetFiles/Files.zip?filenames={querystring}")]
        Stream GetFiles(string querystring);
    

    通过地址传递的任何查询字符串都将被解析为变量。

    然后在Silverlight客户端,我简单地创建了一个自定义的URI(在您的例子中,假设该文件称为“newreport.xls”),它指向调用“getfile/filename”,那么您的URI将类似于 http://localhost/FileService.svc/GetFile/NewReport.xls

    现在你所要做的就是用类似 HtmlPage.Window.Navigate(page, "_self"); . 这将允许您下载该文件,并保持与以前相同的Silverlight页。