2010年7月28日 星期三

[PERL]-Gtk2Perl on Windows

最近有個案子是用Perl開發Gtk
因為手頭上沒有Unix like環境
所以必須在windows上架構Gtk2Perl的環境

首先要先安裝ActivePerl這樣才能在windows上編譯及執行Perl
下載位置:ActivePerl
注意,這裡建議安裝ActivePerl 5.8.9.827版本比較穩定,
更新的版本在install ppm上會有些不可預期的問題。


再來利用ppm指令載入Gtk相關的模組
ppm install http://gtk2-perl.sourceforge.net/win32/ppm/ExtUtils-Depends.ppd
ppm install http://gtk2-perl.sourceforge.net/win32/ppm/ExtUtils-PkgConfig.ppd
ppm install http://gtk2-perl.sourceforge.net/win32/ppm/Glib-1080.ppd
ppm install http://gtk2-perl.sourceforge.net/win32/ppm/Gtk2-1080.ppd

ppm install http://gtk2-perl.sourceforge.net/win32/ppm/Gtk2-GladeXML-1.005.ppd

接著要安裝GTK+ Development Enviroment
下載位置:Glade/Gtk+ for Windows
這個安裝檔包含glade3,一個Gtk所見即所得的工具

整個Gtk2Perl的開發環境在此已建構完成
接下來實際拉個畫面來試試看
打開glade3拖拉個畫面如下,並另存新檔檔名為GUI.glade:

接著建個文字檔Gtk2Perl.pl,內容如下
use Glib qw/TRUE FALSE/;
use Gtk2 '-init';
use Gtk2::GladeXML;

my $gladexml = Gtk2::GladeXML->new("GUI.glade");
$gladexml->signal_autoconnect_from_package('main');

my $window = $gladexml->get_widget('window1');
$window->signal_connect( 'delete_event' => sub{Gtk2->main_quit();});
$window->show_all();

Gtk2->main();

由上面的程式碼可知我們就是用Gtk2::GladeXML這個模組來載入glade編寫出來的.glade檔,
接著直接點擊Gtk2Perl.pl就可以看到執行畫面:

注意,如果執行期發生如下的error
Can't locate object method "signal_connect" via package "Gtk2::Window"
請找出Gtk2.pm檔案,在開頭加上push @Gtk2::Object::ISA, 'Glib::Object';這行即可

最後簡單介紹兩個元件的使用心得
Gtk2::ComboBox,下面的程式碼(非完整)
利用Gtk2::ListStore來做為combobox model的資料來源,
使用Gtk2::CellRendererText來呈現Combobox的欄位,
$FFComboBox->add_attribute ($fy_renderer, "text", ID_COLUMN);
表示render由model的ID_COLUMN欄位取得"text"文字資料
$fy_model = Gtk2::ListStore->new('Glib::String');
foreach (reverse(keys(%fy_all))) {
$fy_model->set($fy_model->append, ID_COLUMN, $_);
}
$FFComboBox->clear();
$FFComboBox->set_model($fy_model);
$fy_renderer = Gtk2::CellRendererText->new;
$FFComboBox->pack_start ($fy_renderer, false);
$FFComboBox->add_attribute ($fy_renderer, "text", ID_COLUMN);
if ($FFComboBox->get_active() == -1) {
$FFComboBox->set_active(0);
}


Gtk2::Dialog,下面是說明一般是如何接受Dialog(與繼承Dialog的模組)的回傳動作,
$config_dialog->set_response_sensitive (0, FALSE);
是說將0註冊為這個dialog的response_id,
然後$config_dialog->run()時會等待該dialog有所動作,並回傳該動作的response_id,
至於dialog的動作就是由button元件觸發,所以button元件會有一個response_id屬性,
用來註明該button動作時會回傳的response_id值,
最後就是利用if (0 eq $config_dialog->run())來判斷按下的是dialog中的那一個按鈕
my $config_dialog = shift @_;
my $text_view = shift @_;

$config_dialog->set_response_sensitive (0, FALSE);
$config_dialog->show();
if (0 eq $config_dialog->run()){
$config_dialog->hide();
}

參考文件:

2010年7月22日 星期四

GTK+ with Dev-C++ on Windows

前言:
        說到C/C++開發環境,就不能不提到GCC。GCC是GNU Compiler Collection (GNU編譯器總集)的縮寫,為GNU計畫中一套多種程式語言編譯器的集合,在諸多Unix-like與Mac OS X中
都成為其內建的程式開發環境。

        其實,GCC最初的名稱為GNU C Compiler (GNU C 語言編譯器)。在當時,GCC還只是一個專門處理 C 語言的編譯器。而在後來 GCC 擴展之後,慢慢的也可以處理C++、Fortran、
Ada、Java、Objective-C 等語言。發展至今,就是現在我們所看到的編譯器總集了。

        雖然在Unix-like與Mac OS X系統中都已經內建了GCC的環境,但是若要在Windows系統下擁有相同的環境,你可能就需要安裝MinGW了。

        MinGW(Minimalist GNU for Windows),又稱Mingw32,為包含了GCC、GDB(GNU Debugger)、binutils等工具的GNU工具組(toolchain)移植到windows平台上的版本。包括一系列表頭檔(Win32API)、函式庫和可執行檔案。 MinGW是從Cygwin(1.3.3版)基礎上發展而來,但是用MinGW開發的程式不需要額外的第三方DLL支援就可以直接在Windows下執行,而且也不一定必須遵從GPL許可證。

進入正題:
下載Dev-C++ 並安裝
Bloodshed Dev-C++ 4.9.9.2 with MinGW for Windows
下載GTK+ Development Enviroment 並安裝
GTK+ Development Enviroment 2.12.9-2 for Windows

接下來檢查GTK+ Path 是否有正確設定於Dev-C++

執行Dev-C++
點選工具列的「Tools -> Compiler Options」,開啟Compiler Options視窗,
點選「Directories」頁籤,點選「Libraries」頁籤,檢查是否含有以下路徑:C:\GTK\LIB

點選「C Includes」「C++ Includes」頁籤,檢查是否含有以下路徑:
C:\GTK\INCLUDE
C:\GTK\INCLUDE\GTK-2.0
C:\GTK\INCLUDE\GLIB-2.0
C:\GTK\INCLUDE\PANGO-1.0
C:\GTK\INCLUDE\CAIRO
C:\GTK\INCLUDE\ATK-1.0
C:\GTK\INCLUDE\GTKGLEXT-1.0
C:\GTK\LIB\GTK-2.0\INCLUDE
C:\GTK\LIB\GLIB-2.0\INCLUDE
C:\GTK\LIB\GTKGLEXT-1.0\INCLUDE
C:\GTK\INCLUDE\LIBGLADE-2.0
C:\GTK\INCLUDE\LIBXML2
 
建立新專案,在新產生的檔案內輸入第一個GTK+的程式碼:
#include 

int main(int argc, char *argv[])
{
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Hello! GTK+!");
gtk_widget_show(window);
gtk_main();
return 0;
}
在Project頁籤內的專案圖示上按右鍵點選「Project Options」點選「Parameters」頁籤
在欄位「Compiler」,輸入以下參數:
-mms-bitfields -IC:\GTK\include\gtk-2.0 -IC:\GTK\lib\gtk-2.0\include -IC:\GTK\include\atk-1.0 -IC:\GTK\include\cairo -IC:\GTK\include\pango-1.0 -IC:\GTK\include\glib-2.0 -IC:\GTK\lib\glib-2.0\include -IC:\GTK\include\libpng12
 
在欄位「Linker」,輸入以下參數:
-LC:\GTK\lib -lgtk-win32-2.0 -lgdk-win32-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lpangowin32-1.0 -lgdi32 -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 -lintl
 
 
compile後執行:
 
compiler參數需要加入-mms-bitfields 的原因:
For reference, here is what the gcc info file has to say about -mms-bitfields:

5.34.3 i386 Variable Attributes
-------------------------------
Two attributes are currently defined for i386 configurations:`ms_struct' and `gcc_struct'
`ms_struct'
`gcc_struct'
If `packed' is used on a structure, or if bit-fields are used it
may be that the Microsoft ABI packs them differently than GCC
would normally pack them. Particularly when moving packed data
between functions compiled with GCC and the native Microsoft
compiler (either via function call or as data in a file), it may
be necessary to access either format.
Currently `-m[no-]ms-bitfields' is provided for the Microsoft
Windows X86 compilers to match the native Microsoft compiler.

2010年7月21日 星期三

[MS-Server]-JDBC連接SQL Server 2005

首先下載三個元件
1.Microsoft SQL Server 2005 Express Edition SP3
    安裝時要選混合認証,並為管理者帳號sa設立一組密碼。
2.SQL Server Management Studio 2005 SP3
3.SQL Server 2005 driver for JDBC
    解壓縮後得到的sqljdbc.jar置於jre/lib/ext下
    筆者實際安裝目錄:C:\Program Files\Java\jre6\lib\ext
    並在classpath下加入這行:C:\Program Files\Java\jre6\lib\ext\sqljdbc.jar
    這樣Class.forName時才找的到driver(後面程式碼會說明)。

接下來為了能夠透過TCP/IP來連接sql server還必需多做下列這個動作
   a.打開SQL Server Configuration Manager -> SQLEXPRESS的協議 -> TCP/IP
   b.右鍵單擊啟動TCP/IP
   c.雙擊進入內容,把IP地址中的IP all中的TCP端口設置為1433
   d.重新啟動SQL Server 2005服務中的SQLEXPRESS服務器
   e.關閉SQL Server Configuration Manager

開下來利用SQL Server Management Studio工具新增一個資料庫"Test"
新增兩個欄位及增加一筆值組如下:
field1   field2
----------------
data1   data2

接下來就是實際的存取範利程式碼
public static void main(String[] args) {
  Connection conn = null;
    try {
      Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
      String url = "jdbc:sqlserver://localhost:1433;DatabaseName=Test";
            
      String user = "sa";
      String password = "50321177";
      conn = DriverManager.getConnection(url, user, password);
      PreparedStatement ps = null;
      ResultSet rs = null;
      String sql = "SELECT * FROM table1";
      ps = conn.prepareStatement(sql);
      rs = ps.executeQuery();
      while (rs.next()) {
        System.out.println(rs.getString("field1"));
        System.out.println(rs.getString("field2"));
      }
      conn.close();
    } catch (Exception e) {
      e.printStackTrace();
  }
}

接下來是額外的補充
在SQL Server 2000 中加載driver和URL路徑的語法是
String driverName = "com.microsoft.jdbc.sqlserver.SQLServerDriver ";
String dbURL = "jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sample ";
而SQL Server 2005 中加載driver和URL路徑的語法是
String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver ";
String dbURL = "jdbc:sqlserver://localhost:1433; DatabaseName=sample ";

2010年7月10日 星期六

[C#]-讀取excel檔案寫入MS SQL Server

最近寫案子有用到C#去讀取excel檔案再寫入MS SQL Server,
這是滿常用到的功能所以在這裡記錄一下。

首先是利用oledb讀取excel檔,再利用OleDbDataAdapter將資料填入DataSet。
OleDbDataAdapter 是 DataSet 和資料來源之間的橋接器,用來擷取和儲存資料。OleDbDataAdapter 會提供這個橋接器,方法是使用 Fill 從資料來源將資料載入 DataSet,並使用 Update 將 DataSet 中所做的變更傳送至資料來源。

OLE DB簡介
OLE DB 是一種以 COM 為基礎、用來存取資料的應用程式發展介面 (Application Programming Interface,API)。OLE DB 可存取以任何格式所儲存的資料 (資料庫、試算表、文字檔等等),只要該格式能夠使用 OLE DB 提供者 (Provider)。每個 OLE DB 提供者都會公開特定資料來源類型 (例如 SQL Server 資料庫、Microsoft Access 資料庫或 Microsoft Excel 試算表) 的資料。

常用的Provider列表
Database                Provider
----------------------------------------------------
Ms SQL server       Provider=SQLOLEDB
Oracle                   Provider=MSDAORA
Ms Access 2003    Provider=Microsoft.jet.OLEDB.4.0
Ms Access 2007    Provider=Microsoft.ACE.OLEDB.12.0
Ms Excel 2003       Provider=Microsoft.jet.OLEDB.4.0
Ms Excel 2007       Provider=Microsoft.ACE.OLEDB.12.0
IBM DB2                Provider=DB2OLEDB

private void button1_Click(object sender, EventArgs e)
{
  // Show the dialog and get result.
  DialogResult result = openFileDialog1.ShowDialog(); 
  if (result == DialogResult.OK) // Test result.
  {
    // get excel file name
    string fileName = openFileDialog1.FileName;
    textBox1.Text = fileName;
    button2.Enabled = true;
    // import excel into datagridview
    string excelConn = "Provider = Microsoft.Jet.OLEDB.4.0 ; 
           Data Source = " + textBox1.Text + ";
           Extended Properties = 'Excel 8.0;HDR=YES'";
    string strExcelSelect = "SELECT * FROM [Sheet1$]";
    OleDbDataAdapter adapter = 
          new OleDbDataAdapter(strExcelSelect, excelConn);
    DataSet dataSet = new DataSet();
    adapter.Fill(dataSet, "ExcelInfo");
    dataGridView1.DataSource = dataSet.Tables["ExcelInfo"].DefaultView;
  }
}
再來是將資料從datagridview中匯入MS SQL Server
雖然 .NET沒有類似JAVA的preparedstatement,但有類似的應用IDbDataParameter。
private void button2_Click(object sender, EventArgs e)
{
  string strDBInsert = "INSERT INTO customers VALUES
       (@name,@hPhone,@oPhone,@addr,@delivery,@midwife,@source)";
  string strConn = "Data Source = 6A-783500-NB\\SQLEXPRESS;
                   Integrated Security = True";
  SqlConnection sqlConn = new SqlConnection(strConn);
  sqlConn.Open();
  SqlCommand sqlCmd = new SqlCommand(strDBInsert,sqlConn);
  progressBar1.Step = 100/dataGridView1.Rows.Count;
  for (int i = 0; i < dataGridView1.Rows.Count; i++)
  {
    try
    {
      sqlCmd.Parameters.Clear();
      sqlCmd.Parameters.AddWithValue
          ("@name", Convert.ToString(dataGridView1[0, i].Value));
      sqlCmd.Parameters.AddWithValue
          ("@hPhone", Convert.ToString(dataGridView1[1, i].Value));
      sqlCmd.Parameters.AddWithValue
          ("@oPhone", Convert.ToString(dataGridView1[2, i].Value));
      sqlCmd.Parameters.AddWithValue
          ("@addr", Convert.ToString(dataGridView1[3, i].Value));
      sqlCmd.Parameters.AddWithValue
          ("@delivery", Convert.ToString(dataGridView1[4, i].Value));
      sqlCmd.Parameters.AddWithValue
          ("@midwife", Convert.ToString(dataGridView1[5, i].Value));
      sqlCmd.Parameters.AddWithValue
          ("@source", Convert.ToString(dataGridView1[6, i].Value));
      sqlCmd.ExecuteNonQuery();
      progressBar1.PerformStep();
      }
    catch (Exception e1)
    {
      continue;
    }
    dataGridView1.Rows[i].DefaultCellStyle.BackColor =
                                          Color.CornflowerBlue;  
  }
  progressBar1.Value = progressBar1.Maximum;
  sqlConn.Close();
}