2013年4月12日 星期五

在ASPNET產出Word檔案的方法

以下提供兩種方式 : 1.使用COM操作Word & 2. 產出Html內容, 用下載檔案方式

1.使用COM的方式

使用 CodeBehind 方式進行coding

a)加入引用

using Microsoft.Office.Core;
using Word = Microsoft.Office.Interop.Word;
using System.Text;
using System.Reflection;

記得要引用 Microsoft.Office.Core (Microsoft Office 12.0 Object Library)

b)程式操作word

protected void Page_Load(object sender, EventArgs e)
        {
            object oMissing = System.Reflection.Missing.Value;
            object oEndOfDoc = "\\endofdoc"; /* \endofdoc is a predefined bookmark */

            //Start Word and create a new document.
            Word._Application oWord;
            Word._Document oDoc;
            oWord = new Word.Application();
            oWord.Visible = true;
            oDoc = oWord.Documents.Add(ref oMissing, ref oMissing,ref oMissing, ref oMissing);

            //Insert a paragraph at the beginning of the document.
            Word.Paragraph oPara1;
            oPara1 = oDoc.Content.Paragraphs.Add(ref oMissing);
            oPara1.Range.Text = "Heading 1";
            oPara1.Range.Font.Bold = 1;
            oPara1.Format.SpaceAfter = 24;    //24 pt spacing after paragraph.
            oPara1.Range.InsertParagraphAfter();

            //Insert a paragraph at the end of the document.
            Word.Paragraph oPara2;
            object oRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
            oPara2 = oDoc.Content.Paragraphs.Add(ref oRng);
            oPara2.Range.Text = "Heading 2";
            oPara2.Format.SpaceAfter = 6;
            oPara2.Range.InsertParagraphAfter();

            //Insert another paragraph.
            Word.Paragraph oPara3;
            oRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
            oPara3 = oDoc.Content.Paragraphs.Add(ref oRng);
            oPara3.Range.Text = "This is a sentence of normal text. Now here is a table:";
            oPara3.Range.Font.Bold = 0;
            oPara3.Format.SpaceAfter = 24;
            oPara3.Range.InsertParagraphAfter();

            //Insert a 3 x 5 table, fill it with data, and make the first row
            //bold and italic.
            Word.Table oTable;
            Word.Range wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
            oTable = oDoc.Tables.Add(wrdRng, 3, 5, ref oMissing, ref oMissing);
            oTable.Range.ParagraphFormat.SpaceAfter = 6;
            int r, c;
            string strText;
            for (r = 1; r <= 3; r++)
                for (c = 1; c <= 5; c++)
                {
                    strText = "r" + r + "c" + c;
                    oTable.Cell(r, c).Range.Text = strText;
                }
            oTable.Rows[1].Range.Font.Bold = 1;
            oTable.Rows[1].Range.Font.Italic = 1;

            //Add some text after the table.
            Word.Paragraph oPara4;
            oRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
            oPara4 = oDoc.Content.Paragraphs.Add(ref oRng);
            oPara4.Range.InsertParagraphBefore();
            oPara4.Range.Text = "And here's another table:";
            oPara4.Format.SpaceAfter = 24;
            oPara4.Range.InsertParagraphAfter();

            //Insert a 5 x 2 table, fill it with data, and change the column widths.
            wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
            oTable = oDoc.Tables.Add(wrdRng, 5, 2, ref oMissing, ref oMissing);
            oTable.Range.ParagraphFormat.SpaceAfter = 6;
            for (r = 1; r <= 5; r++)
                for (c = 1; c <= 2; c++)
                {
                    strText = "r" + r + "c" + c;
                    oTable.Cell(r, c).Range.Text = strText;
                }
            oTable.Columns[1].Width = oWord.InchesToPoints(2); //Change width of columns 1 & 2
            oTable.Columns[2].Width = oWord.InchesToPoints(3);

            //Keep inserting text. When you get to 7 inches from top of the
            //document, insert a hard page break.
            object oPos;
            double dPos = oWord.InchesToPoints(7);
            oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range.InsertParagraphAfter();
            do
            {
                wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
                wrdRng.ParagraphFormat.SpaceAfter = 6;
                wrdRng.InsertAfter("A line of text");
                wrdRng.InsertParagraphAfter();
                oPos = wrdRng.get_Information
                               (Word.WdInformation.wdVerticalPositionRelativeToPage);
            }

 

            while (dPos >= Convert.ToDouble(oPos));
            object oCollapseEnd = Word.WdCollapseDirection.wdCollapseEnd;
            object oPageBreak = Word.WdBreakType.wdPageBreak;
            wrdRng.Collapse(ref oCollapseEnd);
            wrdRng.InsertBreak(ref oPageBreak);
            wrdRng.Collapse(ref oCollapseEnd);


            //Add text after.
            wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range;
            wrdRng.InsertParagraphAfter();
            wrdRng.InsertAfter("THE END.");

            //Close this form.
            //this.Close();
        }

 

 

2.產出Html內容方式

假設用CodeBehind的方式,

a)aspx.cs的部份如下:

protected void btnGenerateDocument_Click(object sender, EventArgs e)
    {
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.Charset = "";
       
        HttpContext.Current.Response.ContentType = "application/msword";
       
        string strFileName = "GenerateDocument"  + ".doc";
        HttpContext.Current.Response.AddHeader("Content-Disposition", "inline;filename=" + strFileName);

        StringBuilder strHTMLContent = new StringBuilder();
       
        strHTMLContent.Append(" <h1 title='Heading' align='Center' style='font-family:verdana;font-size:80%;color:black'><u>Document Heading</u> </h1>".ToString());
        strHTMLContent.Append("<br>".ToString());
        strHTMLContent.Append("<table align='Center'>".ToString());
        strHTMLContent.Append("<tr>".ToString());
        strHTMLContent.Append("<td style='width: 100px;background:#99CC00'><b>Column 1</b></td>".ToString());
        strHTMLContent.Append("<td style='width: 100px;background:#99CC00'><b>Column 2</b></td>".ToString());
        strHTMLContent.Append("<td style='width: 100px;background:#99CC00'><b>Column 3</b></td>".ToString());
        strHTMLContent.Append("</tr>".ToString());
        strHTMLContent.Append("<tr>".ToString());
        strHTMLContent.Append("<td style='width: 100px'>a</td>".ToString());
        strHTMLContent.Append("<td style='width: 100px'>b</td>".ToString());
        strHTMLContent.Append("<td style='width: 100px'>c</td>".ToString());
        strHTMLContent.Append("</tr>".ToString());
        strHTMLContent.Append("<tr>".ToString());
        strHTMLContent.Append("<td style='width: 100px'>d</td>".ToString());
        strHTMLContent.Append("<td style='width: 100px'>e</td>".ToString());
        strHTMLContent.Append("<td style='width: 100px'>f</td>".ToString());
        strHTMLContent.Append("</tr>".ToString());
        strHTMLContent.Append("</table>".ToString());
        strHTMLContent.Append("<br><br>".ToString());
        strHTMLContent.Append("<p align='Center'> Note : This is dynamically generated word document </p>".ToString());
           
      
        HttpContext.Current.Response.Write(strHTMLContent);
        HttpContext.Current.Response.End();
        HttpContext.Current.Response.Flush();
    }

 

b)aspx部份

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="GenWord.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="btnGenerateDocument" runat="server" OnClick="btnGenerateDocument_Click"
            Text="Generate Document" /></div>
    </form>
</body>
</html>

供各位參考.

2013年3月13日 星期三

關於VS2010 Setup Project的問題

我有建一個多個project的安裝檔案(Molds), 引入了約5、6個Projects, 剛建好時似乎是OK的, 但是經過一段時間(專案維護), 出現下列錯誤:

Unable to update the dependencies of the project cannot be determined

這個問題其它是專案增加(Add Project output)時的依存性(dependencies)檢查出問題, 微軟有hotfix http://support.microsoft.com/kb/2286556?wa=wsignin1.0

在connect也有https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=30681

我現在的作法是不用它的Add Project output 的功能, 自己找檔案(dll) 加入.

就解決了.

2013年3月2日 星期六

Toolbox items in DSL tools

In this post:

1) General overview of the way the toolbox items work in DSL tools for VS2010

2) Toolbox related Changes from VS2008 to VS2010

3) Customization of static toolbox items - how to grouped model elements into single toolbox item

In VS 2010 we change the way we manage toolbox items from being set explicitly during package initialization to being partially set(*) before the package has been created and initialized. The toolbox items that are set this way called static toolbox items (vs. dynamic toolbox items in VS2008).

* By partially I mean only the text, tooltip and icon are set (there are few more but they are there for technical reasons) – no action or any DSL-specific information is associated with the toolbox item –practically those toolbox items are stubs until their full initialization.

Q: Why did moved to static toolbox items?

A: By using this approach we were able to speed up the overall VS loading time because no package will be created (and initialized) prematurely just because it has some toolbox items.

The full initialization will occur when the specific designer will show up and someone will hover the toolbox item and at that point the partial toolbox items will be replaced with ModelingToolboxItem that will be created according to the following sequence diagram:

image

Blue line – VS will use package.GetToolboxItemData(..) to try and get the toolbox item data for each of the toolbox items ids you’ve hovered to replace it with the stub toolbox item and cache it in VS toolbox cache.

Red Line – Toolbox helper will create an instance of ModelingToolboxItem according to the toolbox item id.

Q: How would I add custom static toolbox items that are not mapped to a shape or logically group several model elements into single toolbox item?

A: The recommended approach is to add class attribute on partial package class (in DslPackage) and extending the ToolboxHelper class (in Dsl) and supporting the new toolbox item id.

Example for language name “MyLanguage”:

Under DslProject project:

   1: // See the generated Package.cs for examples
   2: [ProvideStaticToolboxItem(…, “MyNamesSpace.MyNewToolboxItem”,….)]
   3: partial class MyLangaugePackage : MylLanguagePackageBase
   4: {
   5: }


More info: ProvideStaticToolboxItemAttribute


Under Dsl project:

   1: partial class MyLanguageToolboxHelper : MyLanguagelToolboxHelperBase
   2: {
   3:     public override ModelingToolboxItem GetToolboxItem(string itemId, Store store)
   4:     {
   5:         if (store == null)
   6:         {
   7:             return null;
   8:         }
   9:         if (itemId != “MyNamesSpace.MyNewToolboxItem”)
  10:         {
  11:             return base.GetToolboxItem(itemId, store);
  12:         }
  13:  
  14:             
  15:         // return the custom toolbox item instance 
  16:         // see the generated ToolboxHelper.cs code for examples
  17:         return 
  18:             new ModelingToolboxItem(“MyNamesSpace.MyNewToolboxItem”,
  19:                         1, 
  20:                         …,
  21:                         …,
  22:                         …,
  23:                         …,
  24:                         …,
  25:                         …,
  26:                         CreateMyCustomPrototype(store), 
  27:                         …
  28:                         });
  29:     }
  30:  
  31:     private static ElementGroupPrototype CreateMyCustomPrototype (Store store)
  32:     {
  33:         ElementGroup elementGroup = new ElementGroup(store.DefaultPartition);
  34:  
  35:         // add all the model elements that create a logical group
  36:         // make sure to set the properties that will be used as defaults
  37:         elementGroup.AddGraph(/*Add model element 1 instance*/, true);
  38:         elementGroup.AddGraph(/*Add model element 2 instance */, true);
  39:         elementGroup.AddGraph(/*Add model element 3 instance */, true);
  40:         return elementGroup.CreatePrototype();
  41:     }
  42: }


More info: ModelingToolboxItem


Published Tuesday, January 19, 2010 3:26 PM by Eyal

תגים:C#, SDK, DSL, Best Practices, DEV, Visual Studio 2010, .NET 4.0, Visual Studio 2008, VS2008, VS10, VS2010


Comments

# re: Toolbox items in DSL tools@ Wednesday, July 04, 2012 8:26 PM

-1'

by 1

# re: Toolbox items in DSL tools@ Tuesday, December 11, 2012 5:29 AM

That takes us up to the next level. Great psoting.

by Keys

2013年2月28日 星期四

Apache+PHP5 使用Mysql遇到的問題

Window 7 重灌後, 重拾PHP的專案, 啟動時遇到的問題, 在 Phpinfo 內怎樣都看不到MySql載入, php.ini 也都沒有設定錯, 查看 Apache 的 error.log 出現如下

PHP Warning:  PHP Startup: Unable to load dynamic library 'C:\\AppServ\\php5\\ext\\php_mysql.dll' - The specified module could not be found.\r\n in Unknown on line 0

原因不是別的, 只是少了 libmysql.dll ;

把libmysql.dll複製一份到C:\Windows\System32就好了.

PS: 請注意你的libMySql.dll 的 版本與 php 相同.

2013年2月21日 星期四

在Google Sites(協作) 使用 Goolge Driver(Google Docs)的資料夾文件

參考https://developers.google.com/apps-script/articles/embedding_docslist_in_sites的作法

在Site的管理界面, 新增一個Script

function showFolderInSite() {
var files = DocsList.getFolderById('Google資料夾ID').getFiles();
var page = SitesApp.getPageByUrl('要出現的協作網頁網址');
var attachments = page.getAttachments();

for (i in attachments) {
attachments[i].deleteAttachment();
}

for (i in files) {
page.addWebAttachment(files[i].getName(), '', files[i].getUrl());
}
}

 

1.替換程式內資料夾ID

 


2.替換程式內網頁的URL


image


 


整個結果大致如下


image


 


再回到協作去看就可以看到同步過來的檔案了, 但是如果Driver有再新增檔案, 必須再執行一次Script, 應該還有其它方法吧. 有空再研究.

2013年2月18日 星期一

MS-SQL 2008 msdb missing(遺失)

今天做了一件很蠢的事, 我竟然不認識msdb, 把 MSDBData.mdf 給永久刪除了.

結果重新開機再次進入SQL Server Management Studio時, 出現了

TITLE: Microsoft SQL Server Management Studio
------------------------------

Failed to retrieve data for this request. (Microsoft.SqlServer.Management.Sdk.Sfc)

For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&LinkId=20476

------------------------------
ADDITIONAL INFORMATION:

An exception occurred while executing a Transact-SQL statement or batch. (Microsoft.SqlServer.ConnectionInfo)

------------------------------

Database 'msdb' cannot be opened due to inaccessible files or insufficient memory or disk space.  See the SQL Server errorlog for details. (Microsoft SQL Server, Error: 945)

For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&ProdVer=10.50.4000&EvtSrc=MSSQLServer&EvtID=945&LinkId=20476

Google後,在 MSDN 找到解答, 關鍵字是  Rebuild System Databases,

重點是要找到安裝光碟(或重新下載download), 找到媒體目錄內的setup.exe . 用命令列重新產生.

提供我的指令供參考.

Setup /QUIET /ACTION=REBUILDDATABASE /INSTANCENAME=SQLEXPRESS /SQLSYSADMINACCOUNTS=BUILTIN\Administrators  /SAPWD= StrongPassword /SQLCOLLATION=Chinese_Taiwan_Stroke_CI_AS

另外注意一點, 你的目錄 MSSQL\Binn\Templates 內有沒有範本檔, 它是用這裡的範本來產生的, 如果沒有, 也要重媒體檔(setup\sql_engine_core_inst_msi\Pfiles\SqlServr\MSSQL.X\MSSQL\Binn\Templates)再複製過來.

執行完成, 是沒有訊息的, 有訊息表示沒有成功, 要檢查你的參數, 檢查 C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Logs 下的 Summary.txt .

2013年1月10日 星期四

BaseHttpHandler

/// <summary>
/// An abstract base Http Handler for all your
/// <see cref="IHttpHandler"/> needs.
/// </summary>
/// <remarks>
/// <p>
/// For the most part, classes that inherit from this
/// class do not need to override <see cref="ProcessRequest"/>.
/// Instead implement the abstract methods and
/// properties and put the main business logic
/// in the <see cref="HandleRequest"/>.
/// </p>
/// <p>
/// HandleRequest should respond with a StatusCode of
/// 200 if everything goes well, otherwise use one of
/// the various "Respond" methods to generate an appropriate
/// response code. Or use the HttpStatusCode enumeration
/// if none of these apply.
/// </p>
/// </remarks>
public abstract class BaseHttpHandler : IHttpHandler
{
/// <summary>
/// Creates a new <see cref="BaseHttpHandler"/> instance.
/// </summary>
public BaseHttpHandler() {}

/// <summary>
/// Processs the incoming HTTP request.
/// </summary>
/// <param name="context">Context.</param>
public void ProcessRequest(HttpContext context)
{
SetResponseCachePolicy(context.Response.Cache);

if(!ValidateParameters(context))
{
RespondInternalError(context);
return;
}

if(RequiresAuthentication
&& !context.User.Identity.IsAuthenticated)
{
RespondForbidden(context);
return;
}

context.Response.ContentType = ContentMimeType;

HandleRequest(context);
}

/// <summary>
/// Indicates whether or not this handler can be
/// reused between successive requests.
/// </summary>
/// <remarks>
/// Return true if this handler does not maintain
/// any state (generally a good practice). Otherwise
/// returns false.
/// </remarks>
public bool IsReusable
{
get
{
return true;
}
}

/// <summary>
/// Handles the request. This is where you put your
/// business logic.
/// </summary>
/// <remarks>
/// <p>This method should result in a call to one
/// (or more) of the following methods:</p>
/// <p><code>context.Response.BinaryWrite();</code></p>
/// <p><code>context.Response.Write();</code></p>
/// <p><code>context.Response.WriteFile();</code></p>
/// <p>
/// <code>
/// someStream.Save(context.Response.OutputStream);
/// </code>
/// </p>
/// <p>etc...</p>
/// <p>
/// If you want a download box to show up with a
/// pre-populated filename, add this call here
/// (supplying a real filename).
/// </p>
/// <p>
/// </p>
/// <code>Response.AddHeader("Content-Disposition"
/// , "attachment; filename=\"" + Filename + "\"");</code>
/// </p>
/// </remarks>
/// <param name="context">Context.</param>
public abstract void HandleRequest(HttpContext context);

/// <summary>
/// Validates the parameters. Inheriting classes must
/// implement this and return true if the parameters are
/// valid, otherwise false.
/// </summary>
/// <param name="context">Context.</param>
/// <returns><c>true</c> if the parameters are valid,
/// otherwise <c>false</c></returns>
public abstract bool ValidateParameters(HttpContext context);

/// <summary>
/// Gets a value indicating whether this handler
/// requires users to be authenticated.
/// </summary>
/// <value>
/// <c>true</c> if authentication is required
/// otherwise, <c>false</c>.
/// </value>
public abstract bool RequiresAuthentication {get;}

/// <summary>
/// Gets the content MIME type.
/// </summary>
/// <value></value>
public abstract string ContentMimeType {get;}

/// <summary>
/// Sets the cache policy. Unless a handler overrides
/// this method, handlers will not allow a respons to be
/// cached.
/// </summary>
/// <param name="cache">Cache.</param>
public virtual void SetResponseCachePolicy
(HttpCachePolicy cache)
{
cache.SetCacheability(HttpCacheability.NoCache);
cache.SetNoStore();
cache.SetExpires(DateTime.MinValue);
}

/// <summary>
/// Helper method used to Respond to the request
/// that the file was not found.
/// </summary>
/// <param name="context">Context.</param>
protected void RespondFileNotFound(HttpContext context)
{
context.Response.StatusCode
= (int)HttpStatusCode.NotFound;
context.Response.End();
}

/// <summary>
/// Helper method used to Respond to the request
/// that an error occurred in processing the request.
/// </summary>
/// <param name="context">Context.</param>
protected void RespondInternalError(HttpContext context)
{
// It's really too bad that StatusCode property
// is not of type HttpStatusCode.
context.Response.StatusCode =
(int)HttpStatusCode.InternalServerError;
context.Response.End();
}

/// <summary>
/// Helper method used to Respond to the request
/// that the request in attempting to access a resource
/// that the user does not have access to.
/// </summary>
/// <param name="context">Context.</param>
protected void RespondForbidden(HttpContext context)
{
context.Response.StatusCode
= (int)HttpStatusCode.Forbidden;
context.Response.End();
}
}