2007年11月26日 星期一

ASP.NET 動態轉換繁體Crystal Report報表(*.rpt)成簡體版?

ASP.NET 動態轉換繁體Crystal Report報表(*.rpt)成簡體版?

在ASP.NET上使用Crystal Report設計的繁體報表,
如果能動態轉換成簡體, 就能省去同時維護繁體和簡體
二套系統的工作.

在輸出報表的VB中呼叫get_rpt function:


...
Dim reportDoc As New ReportDocument
reportDoc.Load(rptfun.get_rpt(Server.MapPath("xxx.rpt")))
...


rptfun.vb:


Imports CRAXDRT

Public Class rptfun
Public Shared Function get_rpt(ByVal v_file As String) As String
Dim v_cult As String = System.Configuration.ConfigurationSettings.AppSettings("Location").ToString()
If v_cult = "zh-CN" Then
Dim v1 As Integer = InStrRev(v_file, "\")
Dim v2 As Integer = InStrRev(v_file, "\", v1 - 1)
Dim v3 As Integer = v_file.Length
Dim vc3 As String = Right(v_file, v3 - v1)
Dim v_cnfile As String = Left(v_file, v2) + "temp_cn\" + vc3
Return rpt2cn(v_file, v_cnfile)
Else
Return v_file
End If
End Function

Public Shared Function rpt2cn(ByVal v_file As String, ByVal v_fileto As String) As String
Dim oCR As New CRAXDRT.Application
Dim oRpt As Report = oCR.OpenReport(v_file)
Dim jj, kk, ll, pp As Integer
For jj = 1 To oRpt.Areas.Count
For kk = 1 To oRpt.Areas.Item(jj).Sections.Count
For ll = 1 To oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Count
yy = oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll)
If yy.Kind = 2 Then
Dim v_objn As Integer = 0
Dim MTXT As String = Trim(yy.Text)
Dim MRPL As String = MTXT
If Len(MRPL) > 0 Then
MRPL = StrConv(MTXT, VbStrConv.SimplifiedChinese, 2052)
End If
If yy.FieldElements.Count > 0 Then
v_objn = yy.FieldElements.Count
Dim txtobj(v_objn, 3) As Object
For pp = 1 To v_objn
txtobj(pp, 1) = yy.FieldElements.Item(pp).FieldDefinition
txtobj(pp, 3) = yy.FieldElements.Item(pp).Font.bold
Next
Dim v_star As Integer = 1
For pp = 1 To v_objn
txtobj(pp, 2) = InStr(v_star, MRPL, "[]")
If txtobj(pp, 2) >= v_star Then
v_star = txtobj(pp, 2) + 1
End If
Next
MRPL = Replace(MRPL, "[]", "")
oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll).settext(MRPL)
For pp = 1 To v_objn
yy.FieldElements.Add(txtobj(pp, 2), txtobj(pp, 1))
Next
oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll).Font.Name = "SimSun"
For pp = 1 To v_objn
yy.FieldElements.Item(pp).Font.bold = txtobj(pp, 3)
Next
Else
oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll).settext(MRPL)
oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll).Font.Name = "SimSun"
End If
End If
If yy.Kind = 1 Then
oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll).Font.Name = "SimSun"
End If
Next
Next
Next
oRpt.Save(v_fileto)
Return v_fileto
End Function
End Class


註:
1. web.config 中定義 Location. (<add key="Location" value="zh-CN"/>)
2. ASP.NET 必須設定有寫入temp_cn目錄的權限.
3. 加入參考:CRAXDRT.dll(Crystal Reports ActiveX Designer DLL)

2007年10月8日 星期一

POST上去之後無法在文章中顯示的字

POST上去之後無法在文章中顯示的字,
可以用代碼:


  • < 用 &lt; 取代

  • > 用 &gt; 取代

  • & 用 &amp; 取代


2007年10月7日 星期日

如何將繁體ASP.Net WebSite轉成繁簡體?

如何將繁體ASP.Net WebSite轉成繁簡體?
不管開始寫網頁或已完成的ASPX繁體網站,
要轉簡體版都是一件"繁"人的工作.

早期並不是沒想到國際化, 只因為案子在趕
只好用複製ASPX的方式, 所幸ASPX.VB程式邏輯
都一樣, 就這樣一個專案不知不覺寫到了快80MB,
一千多支程式維護起來己經不容易還要考慮簡體版同步更新......

這下子只好重新思考簡繁同體, 畢竟程式像個活體,
隨著商業流程一直在擴充及修改.
要同時支援繁簡體並不困難,
只是戲法人人會變,各有巧妙不同.

剛開始用正統的國際化寫法,
可是一下子就打退堂鼓了, 原因無他, 程式太大了,
如果都用資源檔Resource Files, 光讀取這個XML檔
並找到對應文字就不知Performance會降到什麼程度,
更別說要如何建立三組龐大的對應文字.
(如果你的專案不大, 而且有第三種以上的語言需求,
建立資源檔Resource Files倒不失為一個好方法).

如果在資料庫建對照表, 尋找對應的速度應該會比較快,
但維護對照表倒不是個很好的經驗. 而且會影响資料庫及網路效能.

言歸正傳, 我目前簡繁同體進行之方法如下:

適用環境:
VS.NET 2003 - VB.NET

1. ASPX Title 部份寫一支共用vb function :


Public Shared Function GetTile(ByVal v_til As String) As String

Dim Tile As String = v_til
Dim v_cult As String = System.Configuration.ConfigurationSettings.AppSettings("Location").ToString()
If v_cult = "zh-CN" Then
Tile = StrConv(Tile, VbStrConv.SimplifiedChinese, 2052)
End If
Return Tile

End Function


註: Web.config 中的appsettings增加:
繁體或簡體手動設定

<appSettings>
<add key="Location" value="zh-CN"/>
......
</appSettings>

在ASPX之HTML中TITLE改成:

<TITLE>
<% =myfuntion.GetTile("購物車明細資料")%>
</TITLE>

2. 把ASPX中不是runat="server"之繁體文字改為
label物件 並加 runat="server"

3. 在所有*.ASPX.VB程式中的Page_Load加入呼叫
Label, CheckBox 及DataGrid轉換Function:


Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not IsPostBack Then
Decode_lab(Me.Controls.Item(0))
End If
End Sub


加一個共用轉換Function:

Public Shared Function Decode_lab(ByVal v_control As Object) As Boolean
Dim v_cult As String = System.Configuration.ConfigurationSettings.AppSettings("Location").ToString()
If v_cult = "zh-CN" Then
Dim iii As Integer
Dim v_labt As String
Dim v_labn As String
For iii = 0 To v_control.Controls.Count - 1
v_labt = v_control.Controls.Item(iii).GetType.Name
If v_labt = "Label" Then
v_labn = v_control.Controls.Item(iii).id
Dim v_lab As Label = CType(v_control.FindControl(v_labn), Label)
v_lab.Text = StrConv(v_lab.Text, VbStrConv.SimplifiedChinese, 2052)
End If
If v_labt = "DataGrid" Then v_labn = v_control.Controls.Item(iii).id
Dim v_grd As DataGrid = CType(v_control.FindControl(v_labn), DataGrid)
Dim iv As Integer
Dim v_grdtc As TemplateColumn
Dim v_grdbc As BoundColumn
For iv = 0 To v_grd.Columns.Count - 1
If v_grd.Columns(iv).GetType.Name = "TemplateColumn" Then
v_grdtc = CType(v_grd.Columns(iv), TemplateColumn)
v_grdtc.HeaderText = StrConv(v_grdtc.HeaderText, VbStrConv.SimplifiedChinese, 2052)
End If
If v_grd.Columns(iv).GetType.Name = "BoundColumn" Then
v_grdbc = CType(v_grd.Columns(iv), BoundColumn)
v_grdbc.HeaderText = StrConv(v_grdbc.HeaderText, VbStrConv.SimplifiedChinese, 2052)
End If
Next
End If
If v_labt = "CheckBox" Then
v_labn = v_control.Controls.Item(iii).id
Dim v_chk As CheckBox = CType(v_control.FindControl(v_labn), CheckBox)
v_chk.Text = StrConv(v_chk.Text, VbStrConv.SimplifiedChinese, 2052)
End If
Next
End If
Return True
End Function


至此轉換工作即可告一段落, 剩下的Crystal報表可以參考我用VFP寫的轉換
(
http://roxsu.blogspot.com/2007/06/crystal-reportrpt.html
)

至於圖檔方面就自己慢慢來吧...

2007年8月20日 星期一

(Web Ajax progress bar)


Visual Studio 2003 Sample project:
http://roxsu.tw.googlepages.com/webtimebar.zip


一直以來常用到後端 SQL 或 AP Server 大量長時間 運算的程序, User 老是以為當機, 找了好久, Web 版計時器始終沒有合用的, 後來只好自己利用 Ajax 完成了 這個不錯用的時間計時器.

2007年6月21日 星期四

如何將繁體Crystal Report(*.RPT)檔轉成簡體?

如何將繁體Crystal Report(*.RPT)檔轉成簡體?

請先準備:
1. Hokoy.WordKit.dll
(http://reg.softking.com.tw/freeware/index.asp?fid1=3&fid2=260&fid3=22195)
2. Crystal Report 正式版 (或安裝Crystal Translator Demo 版)
(http://www.softlang.com/download.htm)
3. Unicode 補完計畫 2.50
(http://uao.cpatch.org/index.php?%E4%B8%8B%E8%BC%89)

參考文件:
Integrating Crystal Reports with Visual FoxPro
(http://www.craigberntson.com/Articles/kb014.htm)

作法:
1. 先用 "RegSvr32" 註冊Hokoy.WordKit.dll.
2. 如果有用到Unicode請安裝 Unicode補完計畫.

VFP8.0 程式範例:
(http://roxsu.tw.googlepages.com/rpt_tran.zip)

*** 用TCtoSC將 D:\RPT\*.RPT(Unicode繁體字)
*** 轉到D:\RPTS\*.RPT(Unicode簡體字)


Set Safety Off
Set Exact On
If Rpl_unicode("D:\RPT\", "D:\RPTS\")
Messagebox("Transfer OK!!")
Endif
Set Safety On

Function Rpl_unicode
Para wic, wicnew

olebig=Createobject('Hokoy.WordKit')

*!* 函式名稱 參數形式 傳回值形式
*!* GBtoBig5 GB Big5
*!* BIG5toGB Big5 GB
*!* GBtoUnicode GB Unicode
*!* Big5toUnicode Big5 Unicode
*!* UnicodetoGB Unicode GB
*!* UnicodetoBig5 Unicode Big5
*!* SCtoTC Unicode簡體字 Unicode繁體字
*!* TCtoSC Unicode繁體字 Unicode簡體字

Local LLC,MTXT,CTMP, MRPL
Local oCR As CRAXDRT.Application
Local oRpt As CRAXDRT.Report

If Para()<>2
=Messagebox('error',48,'error of path!!')
Return .F.
Endif

getfilenum=Adir(getfiles,wic+'*.rpt')
For ii=1 To getfilenum
Wait Wind 'process Prog: '+getfiles[ii,1] At 8,35 Nowait
*-------------------
oCR = Createobject("CrystalRuntime.Application")
oRpt = oCR.OpenReport(wic+ getfiles[ii,1])
For jj=1 To oRpt.Areas.Count
For kk=1 To oRpt.Areas.Item(jj).Sections.Count
For ll=1 To oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Count
yy = oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll)
If yy.Kind=2 && text obj
v_objn =0
v_hasobj=.F. && has obj in text?
*---------------save text - obj to array --------------------
If yy.FieldElements.Count>0
v_objn=yy.FieldElements.Count
v_hasobj=.T.
Dimension txtobj(v_objn,3)
For pp=1 To v_objn
txtobj(pp,1)=yy.FieldElements.Item(pp).FieldDefinition
txtobj(pp,3)=yy.FieldElements.Item(pp).Font.bold && 儲存BOLD狀態
Endfor
Endif
*---------------save text - obj to array -------------------
m.MTXT=Alltrim(yy.Text)
m.MRPL=m.MTXT && for replace
If Len(m.MRPL) > 0 && 一次轉換繁體->簡體UNICODE
v_uncode = olebig.TCtoSC(m.MRPL)
m.MRPL = v_uncode
Endif
If v_hasobj
*---------------save text - obj to text --------------------
For pp=1 To v_objn
txtobj(pp,2)=Atcc('[]',m.MRPL,pp) && 因為ADD用中文算字數所以用ATCC
Endfor
m.MRPL=Strtran(m.MRPL, '[]', '')
oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll).settext(m.MRPL)
For pp=1 To v_objn
yy.FieldElements.Add(txtobj(pp,2),txtobj(pp,1))
yy.FieldElements.Item(pp).Font.bold = txtobj(pp,3)
Endfor
*---------------save text - obj to text -------------------
Else
oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll).settext(m.MRPL)
Endif
oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll).Font.Name="SimSun"
If v_hasobj && bold 字型設定後才有效
For pp=1 To v_objn
yy.FieldElements.Item(pp).Font.bold = txtobj(pp,3)
Endfor
Endif
Endif
If yy.Kind=1
oRpt.Areas.Item(jj).Sections.Item(kk).ReportObjects.Item(ll).Font.Name="SimSun"
Endif
Endfor
Endfor
Endfor
oRpt.Save(Trim(wicnew)+ Alltrim(getfiles[ii,1]))
Endfor
Return .T.
Endfunc

2007年5月30日 星期三

Hole In One

一桿進洞

有人研究過一桿進洞的機率是1/12000,以我一年上場30次的
頻率來算是100年打不到一次,沒想到打了10年球就遇到一次了.

那是一個不怎麼愉快的經驗, 只是事後回憶還算不錯的奇遇.
八月下旬的第一天, 一大早來到一個不太熟悉的桃園球場
(這球場只打過一二次, 又有27洞), 應該是自己太久沒練球,
連輸了17洞狀況不佳下站上西區第九洞發球台,
拿出了最有把握的8I, 心中暗唸著"永不抬頭" 輕輕一揮,
正在慶幸終於擊中甜蜜點的同時小白球ON上果嶺後,
竟不聽使喚地連滾了10多碼進洞了.

天呀! 這種事為何發生在我身上? 一時之間情緒混亂極了,
比高中考試作弊被抓那時還驚慌, 心中直想, 怎麼辦?
眾目睽睽, 臉色凝重, 神情呆滯......(隱約聽到桿弟交耳說:
沒看過有人一桿進洞是這般模樣的...)

除了未婚生子我想不出有什麼事讓當事者欲蓋彌彰,
而親朋好友則爭相走告傳為美談的事來形容當時的心情了.

湊錢給桿弟紅包後因為事逄農曆7月, 聽前輩之言, 也到當地
土地公廟上香致謝一番, 怕的是自己承受不住這樣的"大喜"
所以要分享.

刷卡請客不是最困難的, 倒是如何跟不打球的老婆解釋,
為何我要一桿就把球打進去, 才來花錢買禮物送球友?

其實現在我已經不那麼擔心再一桿進洞了, 一回生二回熟,
除了機率不高外, 頂多只是花錢消災.只是不懂的是多數國人
以為一桿進洞是"災難"事件, 而在老外眼中卻是求之若渴
的"美事"一樁呢!!



(球場送的)





(球隊送的)

2007年5月24日 星期四

Who is here?

加一些簡單的 JAVA SCRIPT 就能分析到這個結果:


(線上訪客分佈圖)

太神奇了...

2007年5月19日 星期六

Golf Swing Analysis Software

如果你剛好是高爾夫的愛好者,
如果你正好想改進你的揮桿姿勢,
這裡有個不錯的分析軟體

Golf Swing Analysis Software (Free Download)



2009:
請先安裝 Microsoft .NET Framework 2.0 或更新版本: (Traditional Chinese)

2007:

2007年5月17日 星期四

如何利用 MSN messenger 自動傳送訊息 (ASP.NET)?

如何利用 MSN messenger 自動傳送訊息 (ASP.NET)?
如果你覺得用 EMail 通知有點緩不濟急,那 MSN 也是個不錯的選擇.
你要事先準備:

DotMSN.dll (http://msluder.dk/DOTMSN/)
MSN 帳號

作法:

1. 加入參考: DotMSN.dll
2.

Imports DotMSN

...

Dim messenger As DotMSN.Messenger = New Messenger
messenger.Connect("你的msn帳號", "你的msn密碼")
messenger.Owner.Name = "你的msn暱稱"
messenger.SynchronizeList()
Thread.Sleep(2000)
messenger.SetStatus(MSNStatus.Online)
Thread.Sleep(1000)
Dim v_msn As String = "對方之MSN帳號"
Dim tmp_con As Conversation = messenger.RequestConversation(v_msn)
Thread.Sleep(2000)
tmp_con.SendMessage("要通知的訊息內容")
Thread.Sleep(1000)
messenger.CloseConnection()

How to read Excel file in ASP.NET?

How to read Excel file in ASP.NET?

在VB.NET有二種常用方法處理 Excel 檔案. 一種是用 Microsoft Office 元件如:

Dim oExcel As New Excel.Application()
...

但是
(Microsoft recommend not using COM Interop with Microsoft Office
products from an ASP.NET web page)

除了要在 Server 裝 Office 外, 還有權限問題要克服.
另一種是用 Microsoft Jet Engine 如 Microsoft MSDN 範例:


Dim DS As System.Data.DataSet
Dim MyCommand As System.Data.OleDb.OleDbDataAdapter
Dim MyConnection As System.Data.OleDb.OleDbConnection

MyConnection = New System.Data.OleDb.OleDbConnection(_
"provider=Microsoft.Jet.OLEDB.4.0; " & _
"data source=C:\myData.XLS; " & _
"Extended Properties=Excel 8.0;")

' Select the data from Sheet1 of the workbook.
MyCommand = New System.Data.OleDb.OleDbDataAdapter( _
"select * from [Sheet1$]", MyConnection)

DS = New System.Data.DataSet()
MyCommand.Fill(DS)
MyConnection.Close()


其中我遇到的小問題是,
當我不知道Excel檔案中Sheet名稱是否叫Sheet1
我必須先找出第一個Sheet Name:


MyConnection.Open()

Dim schemaTable As DataTable
schemaTable = MyConnection.GetOleDbSchemaTable(_
OleDbSchemaGuid.Tables, New Object(_
) {Nothing, Nothing, Nothing, "TABLE"})

MyConnection.Close()
Dim v_sheet1 As String = schemaTable.Rows(0).Item(_
"TABLE_NAME").ToString()

schemaTable.Clear()


之後我就可以把:


MyCommand = New System.Data.OleDb.OleDbDataAdapter( _
"select * from [Sheet1$]", MyConnection)

改成:

MyCommand = New System.Data.OleDb.OleDbDataAdapter( _
"select * from [" + v_sheet1 + "$]", MyConnection)

這樣就可以讀取第一個 Sheet 的資料到 DataSet DS 中了.

2007年5月15日 星期二

短句

  • 新手在乎距離、老手在乎準度,只有高手懂得用球技創造打球的樂趣。
  • 最重要的球技不在接近洞口,而是如何去脫離障礙。
  • 策略可以彌補球技的不足,球技卻無法排除策略的錯誤。

------------- Golf -------------

  • 上帝給我們足夠的時間作任何事,卻不夠無所事。
  • 程式設計師應該是最短利的藝術家,因為他不需等死後才值錢。
  • 生活像是成功嶺煮出來的湯,有色卻無味。
  • As long as your house has Windows, it won't be safe.
  • 你要培養你的耐心, 除了釣魚外,還可以用這個系統(Windows)。

-------------- Life -------------

Blog

好方便的 BLOG.

Remove the NavBar:

#navbar-iframe {display: none;}

/* Variable definitions