2015年11月2日 星期一

Javascript產出Excel

有時碰到有些資料表(Data Grid)因為Server Side運算時間很久或資料量大 

便不希望再次由Server端回傳Excel 

而既然瀏覽器端上已經有運算結果的資料,就可直接用來產生Excel檔案,因此找了一個適用於IEChrome的處理方法,紀錄一下。 

其概念在非IE的瀏覽器上,透過HTML<a>將檔案回傳,類似以下的結構 

<a 
download="fileName.xls" href="data:application/vnd.ms-excel;base64,(base64編碼)"></a> 

其中只是將資料表以Html Table的字串方式透過base64編碼。 

而在IE的瀏覽器上則是透過ActiveXObject直接開啟Excel並直接使用Script產出結果,還滿有意思的~可以試試看!(雖然又被IE玩了一次....)

function exportExcel(){
    // Html Table資料
   
var table = "<table>" +
                   
"<tr><th>Name</th><th>Age</th><th>Score</th></tr>" +
                   
"<tr><td>Scott</td><td>13</td><td>90</td>" +
                   
"<tr><td>Tiger</td><td>14</td><td>70</td></tr>" +
               
"</table>";
                 // IE11後的ActiveXObject判斷方式不同...
   
var isIE = window['ActiveXObject'] || "ActiveXObject" in window ? 
               true : false;
   
if (!isIE) {
       
var uri = 'data:application/vnd.ms-excel;base64,'
           
, template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>'
           
, base64 = function (s) {
               
return window.btoa(unescape(encodeURIComponent(s)))
            }
            , format =
function (s, c) {
               
return s.replace(/{(\w+)}/g, function (m, p) {
                   
return c[p];
                })
            };

       
var ctx = {worksheet: 'Worksheet', table: table.innerHTML};
       
var a = document.createElement('a');
       
a.href= uri + base64(format(template, ctx));
       
a.download=reportMaster.reportName+".xls";
       
a.click();
   
} else {
       
var i, j, str,
           
rowCount = table.rows.length,
            // Activates Excel
           
excel = new ActiveXObject('Excel.Application');
        // Opens a new Workbook
       
excel.Workbooks.Add(); 
        // Shows Excel on the screen
       
excel.Application.Visible = true;
       
for (i = 0; i < rowCount; i++) {
           
for (j = 0; j < table.rows[i].cells.length; j++) {
               
str = table.rows[i].cells[j].innerText;
               
if(str!==null&&str!=='undefined'){
                    // Writes to the sheet
                   
excel.ActiveSheet.Cells(i + 1, j + 1).Value = str
                }
                   
           
}
        }
    }
}


2015年10月28日 星期三

IE11瀏覽器的判斷方式


ActiveXObject undefine

節錄微軟官方的一段說明.....
Starting with IE11, the navigator object supports plugins and mimeTypesproperties. In addition, the window.ActiveXObject property is hidden from the DOM. (This means you can no longer use the property to detect IE11.)

微軟的IE....又改了....IE10之前可以直接判斷window有沒有ActiveXObject來分辨是不是IE瀏覽器,IE11將ActiveXObject改成隱藏....所以不能直接判斷,需要改成 "ActiveXObject" in window 的方式如下....

var isIE=window['ActiveXObject'] ? true :
         "ActiveXObject" in window ? true : false;


紀錄一下....被IE陰了的紀錄....

2015年10月8日 星期四

網頁GZIP壓縮設定


 開發網頁時,若碰到內容較多的表單類或是資料表格(Data table or Data grid),常會讓網頁本身的文字內容就很肥大。

尤其若碰到需要引用一些javascript liberaryextjs or flex這種本身就很肥的東西,常常光基本結構還沒有放入任何內容就已經超過2-3MB了,開發測試時可能還感覺不出來,因為大部分都會在本地端開發,但是只要放在正式環境時就會看的出來影響了。

壓縮HTTP內容(HTTP Compression)


所以如果可以將資料壓縮後再傳送,就可以節省許多頻寬在傳輸上了。如下圖示可看的出來減少了網路所傳輸的資料量,但相對的會增加Server壓縮檔案及Browser解壓縮的消耗。



壓縮的效益


壓縮及解壓縮會消耗ServerBrowserCPU,但設定得宜的話,可以大大減少User等待網路的時間,因此視網站的資料情況設定合適的參數是很重要的。

而影音、圖片及壓縮檔案因大部分已經經過壓縮處理,因此不適合再透過Server做壓縮,會導致增加壓縮成本但網路傳輸量卻減少的有限的反效果。

建議只設定三種格式做壓縮,HTMLCSSJavascript。若透過JSON格式取大量資料的話,也可另外增加application/json的設定將其補上。

Tomcat GZIP Compression設定


找到${tomcat_home} /conf/server.xml,修改Connector的設定

<Connector port="8080" maxHttpHeaderSize="8192"
           maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
           enableLookups="false" redirectPort="8443" acceptCount="100"
           connectionTimeout="20000" disableUploadTimeout="true"
           compression="on"
          
compressionMinSize="2048"
          
noCompressionUserAgents="gozilla, traviata"
          
compressableMimeType="text/html
, text/css, text/xml"/>

屬性說明(Copy From Apache)
compression
The Connector may use HTTP/1.1 GZIP compression in an attempt to save server bandwidth. The acceptable values for the parameter is "off" (disable compression), "on" (allow compression, which causes text data to be compressed), "force" (forces compression in all cases), or a numerical integer value (which is equivalent to "on", but specifies the minimum amount of data before the output is compressed). If the content-length is not known and compression is set to "on" or more aggressive, the output will also be compressed. If not specified, this attribute is set to "off".
Note: There is a tradeoff between using compression (saving your bandwidth) and using the sendfile feature (saving your CPU cycles). If the connector supports the sendfile feature, e.g. the NIO connector, using sendfile will take precedence over compression. The symptoms will be that static files greater that 48 Kb will be sent uncompressed. You can turn off sendfile by setting useSendfile attribute of the connector, as documented below, or change the sendfile usage threshold in the configuration of the DefaultServletin the default conf/web.xml or in the web.xml of your web application.
compressableMimeType
The value is a comma separated list of MIME types for which HTTP compression may be used. The default value istext/html,text/xml,text/plain,text/css,text/javascript,application/javascript .
compressionMinSize
If compression is set to "on" then this attribute may be used to specify the minimum amount of data before the output is compressed. If not specified, this attribute is defaults to "2048".
noCompressionUserAgents
The value is a regular expression (using java.util.regex) matching the user-agentheader of HTTP clients for which compression should not be used, because these clients, although they do advertise support for the feature, have a broken implementation. The default value is an empty String (regexp matching disabled).
  

Weblogic GZIP Compression設定

2.      把下載的jar放到${web_appliaction_home}/WEB-INF/lib
3.      開啟${web_appliaction_home}/WEB-INF/web.xml加入filter的設定
<filter>
    <filter-name>CompressingFilter</filter-name>
    <filter-class>com.planetj.servlet.filter.compression.CompressingFilter</filter-class>
    <init-param>
        <param-name>includeContentTypes</param-name>
        <param-value>text/html,text/css,application/x-javascript</param-value>
    </init-param>
    <init-param>
        <param-name>compressionThreshold</param-name>
        <param-value>256</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>CompressingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

參考資料:

2015年8月12日 星期三

ORA-22922: nonexistent LOB value

ORA-22922: nonexistent LOB value

最近處理了一個原本以為是Java端控制JDBC資料有問題而導致的ORA錯誤,找了半天終於找到可能的原因,紀錄一下免得下次再找半天....

環境敘述

Database : Oracle 10G
Program Language : Java
Application Server : weblogic
Framework : spring 4


錯誤訊息

org.springframework.jdbc.UncategorizedSQLException: StatementCallback;
uncategorized SQLException for SQL [ 
  SELECT *
  FROM (SELECT a.*, ROWNUM r__
          FROM (SELECT *
                  FROM DUMMY_V
                 WHERE (1 = 1)) a
         WHERE ROWNUM < ( (1 * 100) + 1))
  WHERE r__ >= ( ( (1 - 1) * 100) + 1)
];
SQL state [99999]; error code [22922]; ORA-22922: nonexistent LOB value;
nested exception is java.sql.SQLException: ORA-22922: nonexistent LOB value


錯誤分析

其中DUMMY_V是一個View,透過WMSYS.WM_CONCAT將多筆資料合成一筆,為了避免處理CLOB資料型態,所以公司習慣補上to_char將資料轉成varchar,因此寫成了

... select key, to_char(WMSYS.WM_CONCAT(column1 )) from table ...

因此在某些狀況下(可能是資料筆數少),會出現錯誤訊息。原因可能是因為google上找到的某段訊息....

to_char and WM_CONCAT allocated memory size is inconsistent

所以將to_char拿掉後老實處理就解決了.....

資料參考
http://www.javaproblemstips.com/160064/

更新(2015/9/25):
拿掉之後仍在資料較多的情況發生了同樣的訊息,因此後來將本來透過wm_concat將資料串接改成透過trigger串街後存入其他的資料表在查詢的方式處理,因此上述的方法可能沒有完全解決問題,透過11G的LISTAGG會是較好的處理方式(若只有10G以前的版本就.....)

2015年7月8日 星期三

Could not install Gradle distribution from 'https://services.gradle.org/distributions/gradle-xxx-all.zip'


最近在研究Gradle,在公司因為Porxy問題一直撞牆.....想使用Eclipse來用Gradle出現以下錯誤一直找不出原因

Could not install Gradle distribution from 'https://services.gradle.org/distributions/gradle-2.1-all.zip'

要排除這個問題需要以下步驟:
  1. 先去下載所需的Gradle版本(https://gradle.org/gradle-download/)
  2. 解壓縮到任意目錄(這裡是D:\Tools\gradle\gradle-2.4)
  3. 只需要將Eclipse的Gradle Distribution Folder設為所下載的Gradle目錄即可....



2015年2月24日 星期二

Uploadify導致Chrome掛點問題~~(Uploadify Chrome Crash)

紀錄一下工作上遇到的狀況。

有個jQuery上傳多檔案的套件Uploadify,在Chrome會時不時的出現錯誤畫面。


原因是以下這段Code在初始化的時候會發生問題

$("#uploadify_id").uploadify({})...
找到兩個解法
  1. 在import js的時候補上隨機變數,讓瀏覽器每次重新載入js而不使用暫存。
    • <script src="../jquery.uploadify.min.js?ver=<%= Math.round( Math.random() * 10000 ) %> " type="text/javascript"/>
  2. 將Code以setTimeout方式延遲至所有js執行完後再運行。
    1. setTimeout(function () {
          $("#uploadify_id").uploadify({})...
      },0);
實際運行後以第2個方法能正常運行,第一個方法應是已經過時。

而setTimeout(fn,0)的解釋可參考http://pandacafe.net/blog/337

問題發生的可能原因有說是session的,也有說是cookie的,但我猜可能跟swf有關係,也許用HTML5的元件就不會發生這問題了吧?

總之記錄一下囉。

2014年11月2日 星期日

Tomcat設定in Eclipse

1.下載Tomcat。
     下載時需要注意一下所需要開發的程式會用的版本,以下檢附寫文章時的當前版本資訊,下載前可先至http://tomcat.apache.org/whichversion.html確認。
Servlet SpecJSP SpecEL SpecWebSocket SpecApache Tomcat versionActual release revisionSupport Java Versions
3.12.33.01.18.0.x8.0.147 and later
3.02.22.21.17.0.x7.0.566 and later
(WebSocket 1.1 requires 7 or later)
2.52.12.1N/A6.0.x6.0.415 and later
2.42.0N/AN/A5.5.x (archived)5.5.36 (archived)1.4 and later
2.31.2N/AN/A4.1.x (archived)4.1.40 (archived)1.3 and later
2.21.1N/AN/A3.3.x (archived)3.3.2 (archived)1.1 and later
    以目前較穩定的版本是7.0.56,因此下載選擇http://apache.stu.edu.tw/tomcat/tomcat-7/v7.0.56/bin/apache-tomcat-7.0.56.zip,這裡由於要下載的是後續用Eclipse開發時運行的版本,因此不選擇安裝檔案。(Windows環境)

2.下載 Eclipse
     只要到Eclipse官網(http://www.eclipse.org/downloads/)下載即可,基本上由於我們要建立Tomcat,因此要選擇For Jave EE的版本(其中已包含選擇任一版本都可,但要符合作業系統的OS,這裡下載當前最新的64bit版本。
     

3.解壓縮Tomcat及Eclipse後,啟動Eclipse。
     
     
4.Ecilpse需要設定一個workspace,若是第一次設定則會自動建立目錄及所需要的設定檔案,這裡任意定義一個喜歡的地方吧。
     ●啟動Eclipse
     
     ●設定workspace
     
5.設定Tomcat Server
     ●進入Eclipse的畫面後,由File->New->Other開啟Wizard。
     
     ●輸入Server可以快速找到我們要設定的Server
     
     ●輸入Tomcat可以找到我們這次要建立的Tomcat Server類型,這次要設定的是7.0的版本,因此選擇Tomcat v7.0 Server。完成後按下【NEXT】進入下一個設定。
     
     ●這裡的Tomcat installation directory選擇剛才所下載解壓縮的tomcat目錄,而JRE可選擇Eclipse的預設JRE即可。設定完成後可直接按下【Finish】完成。
     
     ●設定完成後可選擇【Java EE】檢視,這時候可以看見左方的Project Explorer出現了Servers的folder,其中包含了此次所設定的Tomcat 7.0。也可在下方的Servers的Tab看見目前Tomcat的狀態。
     
     ●按下Server頁籤的即可啟動Tomcat。
     
     ●按下Server頁籤的即可停止Tomcat