Thursday, October 27, 2016

PostgreSQL - GROUP LIMIT

Salam semua,

Bersawang dah blog ni... lama gila x menulis.

nak share bende baru bagi aku. sebelum ni tak pernah guna advance(sebab aku reti guna select,insert,update,delete shj) SQL.

Pengunaan nya, aku nak group kan mengikut column dan nak limit 3 result teratas sahaja utk setiap grouping.

lepas tanya sifu postgres(Helmi), dia suggest pakai menatang ni.

WITH table_name as (
 ..... complicated queries with join & condition etc......
)  

SELECT
  * 
FROM (
  SELECT
    ROW_NUMBER() OVER (PARTITION BY group_column ORDER BY sort_column) AS r,
    t.*
  FROM
    table_name t) x
WHERE
  x.r <= 3;

As postgres support WITH, so aku prefer asingkan main complicated queries dgn GROUP LIMIT kan. Semua select/join and where condition buat dlm WITH.

Enjoy.

Sunday, August 17, 2014

CORS - Cross Origin Resources Sharing - Isu

JSON FTW... yeay.... everything is JSON... membuatkan hidup anda gembira... hahahhahahhaa.... tapi hilang kegembiraan itu bila error x leh guna JSON yg dah di kongsikan.... hahahahhaha....

Isu yang selalu timbul... xmlhttprequest gagal sebab cross domain request oleh javascript anda... tension kan?... hahhaha

Solusi yg saya pakai adalah... create satu simple server side scipt (perl/php) untuk jalankan tugas ini utk anda. dlm kes ni saya tunjukkan cth mudah mengunakan PHP.

PHP:


$qry_str = $_POST["json"];
if(!$qry_str){
    $qry_str = $_GET["json"];
}

$ch = curl_init();

header("Content-type: application/json");

$http_origin = $_SERVER['HTTP_ORIGIN'];
if(!$http_origin){$http_origin = $_SERVER['HTTP_REFERER'];}

//replace 1234|abcd|... with ur regex origin domain 
if (preg_match('/(1234|abcd)/i', $http_origin)){  
    header("Access-Control-Allow-Origin: $http_origin");n
}

// Set query data here with the URL
curl_setopt($ch, CURLOPT_URL, $qry_str); 

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, '10');
$content = trim(curl_exec($ch));

curl_close($ch);

if($content){
    if ($GET['callback'] != ''){
        print $GET['callback']."( $content )";
    }else{
        $json = json_decode($content);
        
        if(json_last_error() == JSON_ERROR_NONE){
            print $content;
        }else{
            print '{"status": "ERROR","errormsg" : "Invalid Content"}';
        }
        exit; 
    }
    exit;
    
}else{
    print '{"status": "ERROR", "errormsg" : "Empty '.$_GET["json"].'"}';
    exit;
}


kita namakan nya 'json.php'

di javascript kita pula, saya bg cth mengunakan angularjs $http method.

var jsonurl = "http://abc.com/capaian/ke/file/json.json";
        
$http({
    method: 'GET', 
    url: '/json.php?json=' + jsonurl 
}).
success(function(data, status, headers, config) {
    //cek if status == ERROR utk kenalpasti jika ada masalah dgn data anda.
    $scope.prosesdataanda(data)
   
}).
error(function(data, status, headers, config) {
    //hati-hati disini... error bila ada masalah di 'json.php' bukan sumber json anda.
    console.log(data, status);
});

Setel

NGINX - POST request return error

Mengahadapi masalah lagi dgn NGINX. kali ini bila nak post data dari javascript mengunakan xmlhttprequest.

mula2 ingat disebabkan oleh CORS (cross origin resource sharing) isu... puas la godek NGINX sampai lebam.... *penangan x reti nak tgk error log ler ni...

bila terpikir tgk error log.. baru perasan error dia mcm ni:

2014/08/15 10:52:02 [crit] 33772#0: *1 open() "/usr/local/var/run/nginx/client_body_temp/0000000001" failed (13: Permission denied), client: 127.0.0.1, server: hairul, request: "POST /*****/***/json.php/***.geojson HTTP/1.1", host: "hairul:8080", referrer: "http://hairul/******/***/"

bila google terjumpa satu artikel yang menerangkan isu apabila folder 'client_body_temp' dibuat oleh user pertama yang execute, hanya boleh di baca/gunakan oleh user pertama sahaja.... user seterusnya tidak boleh mengunakan folder ini lagi...

Solusinya, define 'client_body_temp_path' untuk setiap virtual host kita.

client_body_temp_path /usr/local/var/run/nginx/client_temp 1 2;

Setel

Friday, July 25, 2014

NGINX - Isu Berkaitan Path/URL

Orang dah beranak pinak, aku baru nak mengurat... hahahha perumpamaan aku dgn NGINX.

sebelum ni aku pakai apache httpd sahaja untuk pembangunan dkt local machine. sblm tu lg aku pakai sambar server. cuma lately ni baru berjinak2 dgn NGINX bila ada keperluan.

Isunya, php script tak jalan bila kita passkan url style REST ... cth: index.php/id/file/lain.

puas godek... almklum la org baru nak bercinta... jumpa gak penyelesaiannya (mungkin bagi anda bende kecik.. tapi besar sungguh masalah ini pada saya... noob la katakan..)

nginx.conf:

location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^((?U).+\.php)(.*)$;

    try_files $fastcgi_script_name =404;

    set $path_info $fastcgi_path_info;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $path_info;
    fastcgi_param PATH_TRANSLATED $document_root$path_info;
    include fastcgi_params;
    
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index index.php;
}

Setel...

Saturday, June 7, 2014

Google Directions Points Decode

https://maps.googleapis.com/maps/api/directions/json?.....

Google Direction API membantu kita untuk mendapatkan laluan dari point A ke point B.

Kalau kita baca balik JSON(prefered) data yang google return, google akan bagi steps start & end location point. dimana kalau kita translate terus diatas peta akan nampak cacat sedikit sebab polyline tak ikut exactly atas jalan.

Goole ada sertakan detail point diantara start & end point, melalui atribute routes->legs->steps[$_]->polyline->points

Cuma, 'cuma' ia telah di encode kan supaya size data nya tidak besar. saya agak sahaja. sebab google ada bagi tips/cara yg digunakan untuk encode points ni. cuma dia tak bagi complete function kat kita.... hampeh kan?... hehehhe

Saya nak buat sendiri x reti... bila cari kat internet diaorg kata dah ada org buat guna javascript tapi saya cari x jumpa... link broken... yang saya jumpa mamat ni dah convert ker PHP code. dia translate dr javascript... saya plak nak kan yg javascript... bila cari tak jumpa... saya translate balik ke javascript.... hahahhaa.... . may be ada mistake.. tapi saya test ok jer... hehehhe

ini code nya dlm javascript function

/*
 * Copyright (c) 2008 Peter Chng, http://unitstep.net/
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * convert to javascipt by hairul@mbek@ayun, http://blog.mbek.net 
*/

function decodePolylineToArray(encoded){
  var length = encoded.length;
  var index = 0;
  var points = [];
  var lat = 0;
  var lng = 0;

  while (index < length)
  {
    // Temporary variable to hold each ASCII byte.
    var b = 0;

    // The encoded polyline consists of a latitude value followed by a
    // longitude value.  They should always come in pairs.  Read the
    // latitude value first.
    var shift = 0;
    var result = 0;
    do
    {
      // The `ord(substr(encoded, $index++))` statement returns the ASCII
      //  code for the character at $index.  Subtract 63 to get the original
      // value. (63 was added to ensure proper ASCII characters are displayed
      // in the encoded polyline string, which is `human` readable)
      //b = ord(substr(encoded, index++)) - 63;
      b = encoded.charCodeAt(index++) - 63;

      // AND the bits of the byte with 0x1f to get the original 5-bit `chunk.
      // Then left shift the bits by the required amount, which increases
      // by 5 bits each time.
      // OR the value into $results, which sums up the individual 5-bit chunks
      // into the original value.  Since the 5-bit chunks were reversed in
      // order during encoding, reading them in this way ensures proper
      // summation.
      result |= (b & 0x1f) << shift;
      shift += 5;
    }
    // Continue while the read byte is >= 0x20 since the last `chunk`
    // was not OR'd with 0x20 during the conversion process. (Signals the end)
    while (b >= 0x20);

    // Check if negative, and convert. (All negative values have the last bit
    // set)
    dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));

    // Compute actual latitude since value is offset from previous value.
    lat += dlat;

    // The next values will correspond to the longitude for this point.
    shift = 0;
    result = 0;
    do
    {
      //b = ord(substr(encoded, index++)) - 63;
      b = encoded.charCodeAt(index++) - 63;
      result |= (b & 0x1f) << shift;
      shift += 5;
    }
    while (b >= 0x20);

    dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
    lng += dlng;

    // The actual latitude and longitude values were multiplied by
    // 1e5 before encoding so that they could be converted to a 32-bit
    // integer representation. (With a decimal accuracy of 5 places)
    // Convert back to original values.
    points.push([lat * 1e-5, lng * 1e-5]);
  }

  return points;
}

Wednesday, February 19, 2014

Apache Cordova

Salam,

sudah lama saya ingin involve dlm mobile application development. tapi java & C# merupakan bahasa alien yg saya tak tercapai2 lagi nak menguasainya... hehehehhehehe

Tahun lepas saya ada cuba phonegap, setelah membaca kebolehan kita develop mobile apps pakai html, css & javascript... excited... install.... dan..... gagal utk dpt run kan hatta sample apps sekalipun... hahahha.... saya ngaku kalah.... saya tinggalkan phonegap dgn perasaan sayu...

dan awal bulan ni.... ada kawan call tanya boleh buat android apps tak.... saya dgn nada sedih ckp tak reti nak buat.... sedih lagi.... tapi saya cuba balik bertanyakan pakcik google manatau phonegap ada ciri2 baru yg lebih memudahkan..... tetiba... terjumpa la CORDOVA (under apache foundation).

Cordova adalah phonegap yg di edarkan secara percuma dibawah apache foundation. dgn cordova (aku terus x pandang/ambik tahu pasal phonegap) ia membenarkan apps kita di compile sendiri tidak seperti mula2 phonegap di lancarkan dimana perlu hantar apps kita untuk dicompile di server phonegap.

Walaupun byk lagi yg aku perlu belajar, tapi cordova membuatkan hati aku berbunga2 kembali... heheheehe..

Setakat ini aku dah buat beberapa simple apps,

  1. launcher web app supaya nampak mcm native apps dlm IOS.
  2. apps mcm instagram & foursquare di combine untuk mengesan lokasi & geocoding sesuatu gambar yg di ambil. beserta sedikit maklumat seperti tajuk & note. yg ni pakai elasticsearch utk query laju.
  3. POC utk satu agensi... yg ni complicated apps skit involve geocoding, photo/image, mobile printing, and client server comunication.

Banyak lagi nak kene belajar.... tapi menyeronokkan...

Wednesday, January 29, 2014

Mojolicious

Salam,

Saya mmg tgh mencari pekerjaan tetap... hehehehe... kalau ada yg nak offer kerja boleh la... terima kasih didahulukan.

Ada hantar resume kat satu company ni... dia dah reply, tetapi kene buat satu assessment test. syarat nya kene pakai Mojolicious (http://mojolicio.us/) framework.

Pertama kali install and bermain dgn mojo ni... slow skit sebab nak pahamkan flow dia etc... as sebelum ni hampir kesemua development pakai framework sendiri. bila nak study framework org ni ambik masa skit.

Assessment dah hantar tak tau le mcmana result... sebab basic sgt buatnya... sebab x abis xplore mojo ni... byk kene study lg...

ada sesiapa biasa pakai? bleh la share skit....

Monday, January 27, 2014

MAX_WAYPOINTS_EXCEEDED

Salam,

Ada request POC utk google mapping replated project. involve direction services dari google map.

Tak dapat nak bagi commitment sebab client tu nak cepat. 2 hari je tempoh yg melalui weekend yang dah ada byk plan nak kene buat.

Tapi tangan masih gatal utk came out dgn something.

Tak dpt nak kongsi kat sini, sebab nama pun POC... kang ken curi lak idea dia... cuma yang nak dikongsi kat sini, Google MAP API v3 ada limitkan waypoints dlm direction service dia...

Maximum kalau x silap hanya 8 waypoint. kene subscribe kepada premium service baru dpt upkan ke 23 waypoint. termasuk origins & destinantion point. kalau tak nanti return status 'MAX_WAYPOINTS_EXCEEDED'.

Waypoint perlu utk bagi route kita tepat. kalau tak nanti dia akan ikut suggested route. dah tak accurate.

Solution terdekat adalah limitkan waypoint kita.

Sunday, December 1, 2013

DIV CSS Border Inside

Salam,

Kalau kita main dengan DIV. bila kita set kan border, div itu akan menjadi lebih panjang/tinggi bergantung kepada berapa pixel kita letak sebagai border kerana line/border itu akan mengelilingi div di bahagian luar.

Untuk sesetengah kes, ini akan menganggu pengiraan anda.

Apa yang saya baru tahu, kita bleh gunakan:

   -moz-box-sizing:    border-box;
   -webkit-box-sizing: border-box;
    box-sizing:        border-box;

Supported on Firefox, Chrome, Safari, Opera and IE8+.

kita akan dpt ini:

saya hensem

instead of:

saya hensem

code penuh css untuk div ini:

.divbox{
 border: 10px solid #ffcc33;
 -moz-box-sizing:    border-box;
 -webkit-box-sizing: border-box;
 box-sizing:        border-box;
 width: 200px;
}

happy coding...

Saturday, November 30, 2013

mysql-bin.***** mengunakan byk space

Salam,

Tiba-tiba terdetik untuk buat backup segala kerja2 di laptop.

baru aku perasan yg folder /usr/local/mysql/data aku makan byk space... hampir 300GB. mula2 aku kira logik lagi sebab aku banyak simpan & pakai data yg besar2 dlm MySQL server aku.

tapi bila tgh buat backup baru perasan yg ada satu pattern file ni ... mysql-bin.***** ada byk dlm folder data/ .... size aeach file maximum dlm 1GB... yg aku nampak ada dekat 200++ file...

aku pun tak pernah tau kewujudan file ni sebelum ni.

Lepas tanya pakcik google, baru tau apa gunanya file ni.

  • Data Recovery
  • High Avaibality/Replication

ada suggestion utk disabled bin log ni... tapi bila pikir2... bende ni perlu... incase jadi apa2... so aku ambil option ke dua utk purge shj existing bin log ni... nak purge gunakan sql command mcm ni

$ mysql -u root -p 'MyPassword' -e "PURGE BINARY LOGS TO 'mysql-bin.03';"

OR

$ mysql -u root -p 'MyPassword' -e "PURGE BINARY LOGS BEFORE '2008-12-15 10:06:06';"

Lepas purge bin log ni... aku dpt reclaim space dlm 150GB++....

kalau nak auto purge... letakkan shj command diatas ni dt cron job.... tapi aku lebih prefer manually.

Saturday, November 23, 2013

Google Map Api V2 Shutdown

Salam Semua.

Lama tak menulis.

Seperti yang semua tahu, Google map API V2 dah shutdown sepenuhnya pada 19hb Novermber 2013.

salah satu client aku yg pakai Google Map API v2 dlm module portal dia terlalu berkira utk invest supaya convert kod semamsa ke V3. aku pun tak ada pilihan selain melihat sejauh mana automagically yg Google Map team claim dlm perubahan dr v2 ke v3 ni.

As aku tunggu dan lihat.... dpt gak la email dr client yg mengatakan some module tak berjalan seperti sepatutnya... kalau ikutkan hati malas nak layan dah. as aku dah cakap awal2.

tapi pikirkan hubungan antara pelanggan... aku tgk2 gak kan la masalah berkaitan Google Map API dia.

untuk convert ke V3 mmg aku x sanggup secara percuma. as boleh dikira buat balik semua sekali.

and apa yg aku jumpa. semua yg lain jalan ok... cuma... 'point' yg kita dpt masa GEvent.addListener ada perubahan sedikit

dari:

var lat = point.x;
var lng = point y;

kepada

var lat = point.ob;
var lng = point.nb;

untuk setakat ni, itu sahaja yang aku jumpa...

****

var lng = point.nb;

Sebelum ni aku update point.pb... ok je... tapi alih2 x bleh plak... kene pakai point.nb.... hahahahha sorryyyy .... ke aku yg dah tuaaaaa....

Wednesday, October 30, 2013

Terlepas Flight

Salam,

Aku terlepas flight.... muahahhahahahha.... hambek ko...

Thursday, October 3, 2013

Accessing Intranet via iPad/IOS

Kadang-kadang anda akan dapati capaian ke intranet(LAN) menggunakan IP ataupun local domain (somelocalserver @ somesite.somelocalserver) x menjadi/tercapai dek iPad/IOS anda.

Untuk sebab tertentu(development) anda mungkin perlukan capaian seperti ini.

Agak pening juga aku nak solve kan isu ni... ntah kenapa ntah... firewall semua dah setting cun... dr pc/laptop/device lain semua OK jer...

Penyelesaian nya agak mudah, renew DHCP server(host yg nak diaccess) atau reconnect/refresh manual IP @ try tukar IP server(host yg nak diaccess).

Try reload/refresh iPad/IOS anda... walla...

hahahhaa... mungkin ada sapa2 boleh terangkan pada aku. tapi utk setakat ini.. mungkin dpt membantu anda yg tgh pening...

wansor desek....

Monday, July 22, 2013

PERL + DBD::Oracle

perghh!!!!! masalah yg hampir serupa berulang dkt Mountain Lion ni....

32bit vs 64bit.... seksa aku nak install perl module utk DBD::Oracle ni.

kene install instantclient dr Oracle. OK DONE..

bila nak build cpan module... perghhh!!!!!!!! azab nya....

and yes, aku berjaya make it running... tapi mcmana? aku x dpt nak terangkan... pusing... pening... hampeh...

hahahahhaha

Thursday, May 30, 2013

Isu JavaScript Antara Domain

Salam,

Lama tak post disini. terasa sibuk yg tak produktif.

saya menghadapi isu bermain dengan javascript apabila memerlukan perhubungan antara domain berbeza.

Sebagai contoh, javascipt di 'origin.site.com' memerlukan/memanggil sumber lain dari 'server.site.com' melalui panggilan XMLHttpRequest(AJAX).

Untuk isu keselamatan, javascript akan menidakkan perhubungan antara domain.

Tetapi jika anda mempunyai kuasa untuk mengubah sumber dari server dimana javascript itu dipanggil, ini ada penyelesaian mudah.

Tambah ini di kepala(header) document anda.

PERL/CGI:

print "Access-Control-Allow-Origin: *"

PHP:

header("Access-Control-Allow-Origin: *")

*diatas ini contoh untuk anda melihat bagaimana ia berfungsi. tetapi config diatas ini membenarkan dokumen anda dicapai oleh semua orang. untuk menhgadkan capaian, anda boleh meletakkan maklumat url yg mencapai dokumen anda. sebagai contoh:

PERL/CGI:

print "Access-Control-Allow-Origin: http://origin.site.com"

PHP:

header("Access-Control-Allow-Origin: http://origin.site.com")

* asingkan mengunakan ',' untuk lebih dari 1 capaian.

Ya, anda juga boleh memanipulasi ini dari bahasa pengatucaraan anda untuk disesuaikan dengan pengunaan & keadaan.

Happy Coding

Sunday, March 3, 2013

PERL + ImageMagick + Mac OS X Mountain Lion

Assalamualikum,

Setelah aku kehilangan sabar sebelum ni akibat byk sgt masalah nak bg imagemagick + perl + Mountain Lion jalan dengan sempurna, aku akhirnya berjaya juga.

Pendekatan yg aku pakai... kalau sampai haywire.. tinggalkan dulu sampai kita lupa semua step yg kita buat. start balik dari 0. hahahaha...

As aku sekarang ni di beri kelapangan masa. aku start balik apa yg aku dah tinggalkan agak lama.

uninstall/install semula ImageMagick

brew uninstall imagemagick
brew install imagemagick --build-from-source

*kalau blum install brew dlm Lion, bleh install pakai tutorial ini
Install Homebrew

dapatkan version imagemagick yg diinstall. atau taip

$>convert -v

Cari/download source imagemagick mengikut version yg telah diinstall.

unzip dan cari folder 'PerlMagick'

$>cd path_to_zip_folder/PerlMagick
$>sudo perl Makefile.PL
$>sudo make
$>sudo make install
$>sudo make test 

Itu sahaja.... kalau x boleh gak... ermmm... cuba lagi...cuba lagi.. dan kalau tak boleh gak .... tinggalkan dulu... dan cuba lg lain kali... muahahhaha...

Harap ini dapat membantu

Wednesday, January 23, 2013

Not In Range - Android based gadget

Menghadapi 1 masalah dgn hp sony Xperia yg pakai OS android. Wireless Not In Range walaupun kita duduk sebelah wireless router. bila connect to hotspot lain ok.

Godek punya godek. jumpa gak akhirnya. Ia berpunca daripada restriction on android itu sendiri. untuk US channel wireless lebih dari 12 dibanned, tak tahu kenapa. so aku syak android auto disabled channel lebih dari 12. effected at android v4.* (icecream sandwich) ke atas.

Solution, so far yang aku jumpa. tukar channel di wireless router kepada channel < 12. try rescan/rfresh wife. sepatutnya android anda akan kembali menjumpai wireless router anda.

TQ

Wednesday, January 16, 2013

'Default Document' berbeza untuk 'Virtual Host' berbeza didalam 'Folder' yg sama

Ada persoalan kenapa nak pakai folder yg sama untuk vhost yg berbeza?
keadaan memerlukan untuk aku berbuat demikian. dan setiap vhost ada 'default document' mereka sendiri.

Pertama sekali, selepas kita create virtual host untuk (cth) vhost.web.com & vhost2.web.com di IIS. dan biasanya kita kene set 'default document' untuk virtual host kita berjalan.

Tetapi oleh kerana kita pointkan kedua2 virtual host td ke folder yg sama. kita akan dpt default document pada fail yg sama.

kalau kita periksa di web folder yg kita dah set tu ada file 'web.config'

kalau kita lihat isi dalam dia lebih kurang begini la isinya:


   
      
         
            
         
      
   

Ubah isi kandungan file web.config kepada:


   
      
         
         
      
   

*just buang yg x perlu je. next time kalau nak pakai balik tinggal tambah je.

Seterusnya, pergi ke:

C:\Windows\System32\inetsrv\config\applicationHost.config

Scroll kepaling bawah fail diatas. cari

'<location path="vhost.web.com"'
atau
'<location path="vhost2.web.com"'

Kalau tidak jumpa, tambah sebelum penutup
'</configuration>'

Ubah/kemaskini/tambah fail diatas dengan:


 
  
   
    
    
   
  
 



 
  
   
    
    
   
  
 

Restart Virtual Host anda. kalau x boleh gak... x dapek den nak nolong... hahahhahaha

listen..listen...listen...... hahahahha... jgn tak listen.. jgn tak listen

* <clear></clear> boleh buat <clear/> jer... tp kat atas ni bila aku pos dia auto corrected XML tag tu jd mcm tu....

Sunday, December 23, 2012

Parse Excel (*.xls & *.xlsx) File via PERL

Salam,

Lama tak post disini. selepas pemergian abah hujung bulan jun haritu. saya x ada idea nak tulis apa.

Baru hari ni ada kekuatan untuk menulis semula.

Harini saya nak kongsi mcmana nak parse excel fail yg mengunakan format MS Excel 2003(*.xls) dan kebawah serta format MS Excel 2007(*.xlsx).

Saya mengunakan PERL + Spreadsheet module dari CPAN.

Module Spreadsheet yg saya gunakan,

  • Spreadsheet::ParseExcel
  • Spreadsheet::XLSX

dua module di atas saya pilih sebab byk mengunakan function name yg hampir serupa cuma cara awal fail excel dibaca sahaja ada perbezaan dimana fail berformat *xlsx memerlukan iconv untuk dapat dibaca isi kandungannya.

Berikut contoh keratan

Untuk Fail berformat *.xls

################
sub getxls{
################ 
 
 use Spreadsheet::ParseExcel;
 
 opendir THISFILES, "$dir" or die "cannot open dir '$dir'";
 my @allfiles = readdir THISFILES;
 close THISFILES;
 foreach my $file(@allfiles){
  if($file =~ /\.xls$/i && $file !~ /^\~/i){
   
   my $parser   = Spreadsheet::ParseExcel->new();
   my $workbook = $parser->parse("$dir/$file");
   
   if ( !defined $workbook ) {
       #die $parser->error(), ".\n";
       print $parser->error() . "\n";
   }else{
    for my $worksheet ( $workbook->worksheets() ) {
     my ( $row_min, $row_max ) = $worksheet->row_range();
     my ( $col_min, $col_max ) = $worksheet->col_range();
     my $sheetname = $worksheet->get_name();
     print "$sheetname\n";
     
     for my $row ($row_min .. $row_max ) {
      for my $col ($col_min .. $col_max ) {
       my $cells = $worksheet->get_cell( $row, $col);
       my $cell='';
       if($cells){
        $cell = $cells->unformatted(); #unformated
        #$cell = $cells->value(); #clean
        print "$cell\t";
       }
      }
      print "\n";
     }
    }
   }
  }
 }
}

Untuk Fail berformat *.xlsx

################
sub getxlsx{
################
 
 use Spreadsheet::XLSX;
 use Text::Iconv;
 
 opendir THISFILES, "$dir" or die "cannot open dir '$dir'";
 my @allfiles = readdir THISFILES;
 close THISFILES;
 foreach my $file(@allfiles){
  if($file =~ /\.xlsx$/i && $file !~ /^\~/i){
   
   my $converter = Text::Iconv -> new ("utf-8", "windows-1251");
   my $workbook = Spreadsheet::XLSX->new("$dir/$file", $converter);
   
   if ( !defined $workbook ) {
       #die $parser->error(), ".\n";
       print $parser->error() . "\n";
   }else{
    for my $worksheet ( @{$workbook -> {Worksheet}} ) {
     my ( $row_min, $row_max ) = $worksheet->row_range();
     my ( $col_min, $col_max ) = $worksheet->col_range();
     my $sheetname = $worksheet->get_name();
     print "$sheetname\n";
     
     for my $row ($row_min .. $row_max ) {
      for my $col ($col_min .. $col_max ) {
       my $cells = $worksheet->get_cell( $row, $col);
       my $cell='';
       if($cells){
        $cell = $cells->unformatted(); #unformated
        #$cell = $cells->value(); #clean
        print "$cell\t";
       }
      }
      print "\n";
     }
    }
   }
  }
 }
}

if($file =~ /\.xlsx$/i && $file !~ /^\~/i){

Saya tapis untuk hanya fail *.xlsx sahaja diprosess. dan nama fail bermula dgn '~' juga di keluarkan dari senarai. PERL boleh membaca fail yang dhidden tetapi module ini akan menghasilkan ERROR apabila cuba memperosess fail sebegini. fail yg mengandungi '~' dipermulaan merupakan fail yg telah ditandakan untuk dibuang oleh OS ataupun sebagai fail backup. fail ini tidak boleh dilihat melalui fail browser.

happy coding....

Friday, July 6, 2012

Al-Fatihah untuk Arwah Abah

Assalamualikum..

Saya baru sahaja kehilangan insan yang saya sayangi... Abah....

Abah meninggal mengejut selepas balik dari kebun. abah sempat balik kerumah tetapi hanya sempat sampai di muka pintu rumah.

Abah menghembuskan nafas terakhir dipangkuan emak.

Semoga arwah abah ditempatkan di kalangan orang-orang yg beriman dan dikasihi oleh Allah. Amin.

Aku masih tidak dpt menerima hakikat yang abah telah tiada.....