LẬP TRÌNH GIAO DIỆN CƠ BẢN
2.3. Liên kết với Microsoft Excel
a) Giới thiệu:
Để liên kết được với Excel thì chúng ta cần phải làm việc với 1 đối tượng COM của excel. COM là 1 đối tượng được đóng gói theo tiêu chuẩn của Microsoft quy định và nó có thể chạy được trên nhiều nền tảng mà không cần Microsoft Office. Để tạo ra đối tượng COM của Excel trong C#, chúng ta thực hiện như sau:
Mở cửa sổ Solution Explorer, click phải chuột vào Reference chọn Add Reference.
Trong cửa sổ New Reference chọn COM->Type Libraries, tìm thư viện Microsoft Excel 12.0 Object Library (tương ứng với MS Office 2007). Click chọn và bấm OK.
- Sau đó viết thêm câu lệnh gọi thư viện trong Form1.cs:
using Excel = Microsoft.Office.Interop.Excel;
VD : Gọi và hiển thị Excel từ Form:
Trong Form, thêm vào 1 Button:
Double click vào button OPEN để gọi delegate tương ứng:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
// Khởi động chtr Excel
Excel.Application exApp = new Excel1.Application();
// Thêm file temp xls
Excel.Workbook exBook = exApp.Workbooks.Add(
Excel.XlWBATemplate.xlWBATWorksheet);
// Lấy sheet 1.
Excel.Worksheet exSheet = (Excel.Worksheet)exBook.Worksheets[1];
exSheet.Activate();
// Hiển thị MS Excel exApp.Visible = true;
}
Đối tượng COM của Excel bao gồm:
- Application (chương trình Excel).
- Workbook (file xlsx làm việc, có nhiều workbook trong một Application).
- Worksheet (có nhiều Worksheet trong Workbook) b) Mở và lưu 1 file Excel:
Thay vì tạo mới 1 file excel như ví dụ trên, ta có thể mở 1 file excel có sẵn, chỉnh sửa và sau đó lưu lại.
VD : Mở 1 file excel có sẵn và lưu file:
Tạo giao diện như ví dụ 1, thêm vào 1 button "Save":
- Button "OPEN" sẽ dùng để mở 1 file có sẵn (giả sử đường dẫn của file đó là : E:\\Book1.xlsx"
// Tạo đối tượng COM nằm ngoài các sự kiện Excel.Application exApp;
Excel.Workbook exBook;
Excel.Worksheet exSheet
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { // Khởi động chtr Excel
exApp = new Excel1.Application();
// Thêm file temp xls
exBook = exApp.Workbooks.Open("E:\\Book1.xlsx",0,false,5,"","",false, Excel.XlWBATemplate.xlWBATWorksheet);
// Lấy sheet 1.
exSheet = (Excel.Worksheet)exBook.Worksheets[1];
exSheet.Activate();
// Hiển thị MS Excel exApp.Visible = true;
}
Button "SAVE" sẽ dùng để save file (giả sử đường dẫn của lưu file mới là : C:\\Book1.xlsx"
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
// Ẩn chương trình exApp.Visible = false;
// Save file
exBook.SaveAs("C:\\file.xls", Excel1.XlFileFormat.xlWorkbookNormal, null, null, false, false, Excel1.XlSaveAsAccessMode.xlExclusive, false, false, false, false, false);
exApp.Quit();
}
c) Làm việc với excel:
- Ghi và lấy dữ liệu từ excel:
Khi làm việc với các cell (ô) trong excel, COM sẽ quản lý theo Range (nó là 1 khối nhiều ô hay cũng có thể chỉ là 1 ô).
VD2 : Ghi và lấy dữ liệu từ 1 ô excel:
// Range là ô [1,1] (A1)
Excel.Range r = (Excel.Range) exSheet.Cells[1, 1];
// Ghi dữ liệu r.Value2 = "123";
// Ghi dữ liệu trực tiếp lên ô [1,2] (B1) exSheet.Cells[1,2] = "234";'
// Giãn cột
r.Columns.AutoFit();
// Lấy dữ liệu hiển thị lên Textbox(TB1)
this.TB1.Text = Convert.ToString(exSheets.Cells[1,2].Value2);
// Hiển thị chương trình excel exApp.Visible = true;
// Đóng chương trình excel exApp.Quit();
- Tạo 1 biểu đồ trong Excel từ C#
Để vẽ biểu đồ trong Excel, trước tiên cần tạo dữ liệu cho biểu đồ. Việc tạo dữ liệu được thực hiện bằng cách ghi dữ liệu vào các ô Excel
VD : Vẽ biểu đồ cột doanh thu theo quý của 2 công ty A-B có số liệu sau:
A B
Quý 1 100 200
Quý 2 200 180
Quý 3 150 120
Quý 4 300 210
Excel.Application exApp;
Excel.Workbook exBook;
Excel.Worksheet exSheet
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { // Khởi động chtr Excel
exApp = new Excel1.Application();
// Thêm file temp xls
exBook = exApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
// Lấy sheet 1.
exSheet = (Excel.Worksheet)exBook.Worksheets[1];
exSheet.Activate();
//Thêm dữ liệu exSheet.Cells[1, 1] = "";
exSheet.Cells[1, 2] = "Quý 1";
exSheet.Cells[1, 3] = "Quý 2";
exSheet.Cells[1, 4] = "Quý 3";
exSheet.Cells[1, 5] = "Quý 4";
exSheet.Cells[2, 1] = "A";
exSheet.Cells[2, 2] = "100";
exSheet.Cells[2, 3] = "200";
exSheet.Cells[2, 4] = "150";
exSheet.Cells[2, 5] = "300";
exSheet.Cells[3, 1] = "B";
exSheet.Cells[3, 2] = "200";
exSheet.Cells[3, 3] = "180";
exSheet.Cells[3, 4] = "120";
exSheet.Cells[3, 5] = "210";
//Chọn vùng dữ liệu vẽ đồ thị Excel.Range chartRange;
chartRange = exSheet.get_Range("A1", "E3");
//Định nghĩa đồ thị
Excel.ChartObjects xlCharts = (Excel.ChartObjects)exSheet.ChartObjects(Type.Missing);
Excel.ChartObject myChart = (Excel.ChartObject)xlCharts.Add(10, 80, 300, 250);
Excel.Chart chartPage = myChart.Chart;
//Chọn loại đồ thị
chartPage.SetSourceData(chartRange, misValue);
chartPage.ChartType = Excel.XlChartType.xlColumnClustered;
// Hiển thị MS Excel exApp.Visible = true;
}
- Chèn biểu đồ từ Excel vào C#
Để thêm biểu đồ đã vẽ trong Excel vào C#, trước tiên cần lưu biểu đồ thành 1 file hình ảnh, sau đó load file hình ảnh và đưa vào C#.
VD2 : Vẽ đồ thị và hiển thị lên PictureBox:
Như ví dụ trên, ta thêm vào 1 PictureBox, sau đó thêm vào dòng lệnh sau (sau đoạn lệnh vẽ đồ thị của ví dụ trên):
//Lưu đồ thị thành file hình và load file hình
chartPage.Export(@"C:\Do_thi.bmp", "BMP", misValue);
pictureBox1.Image = new Bitmap(@"C:\Do_thi.bmp");
III. BÀI TẬP THỰC HÀNH:
3.1. Bài tập luyện tập:
Bài 1 : Làm quen với Listbox và Combobox.
Viết chương trình nhập điểm đơn giản
- Tạo một giao diện bao gồm 2 Listbox (LB1, LB2), 2 Textbox (TB1,TB2) , 2 Button (Thêm, Xóa) - Cho phép nhập Họ tên và Điểm vào 2 textbox. Khi nhấn button "Thêm", thêm thông tin của SV vào 2 Listbox (cuối danh sách).
- Cho phép xóa sinh viên trong danh sách bằng cách chọn Sinh viên trên Listbox và nhấn button "Xóa".
Bài 2 :
- Tương tự bài 1 nhưng thêm các chức năng sau:
- Khi chọn Họ tên sinh viên để xóa, xóa điểm số tương ứng bên Listbox2.
Bài 3 :
- Tương tự bài 2 nhưng thêm các chức năng sau:
- Thêm 1 button "Tìm kiếm" , 1 Textbox (TB3) và 1 label. Cho phép nhập họ tên tìm kiếm vào Textbox3, khi nhấn button "Tìm kiếm", tìm điểm tương ứng với tên vừa nhập, nếu tìm thấy hiển thị điểm lên label.
Bài 4 :
- Tương tự bài 3 nhưng thêm các chức năng sau:
- Thêm 1 button "Sắp xếp" và 2 Radiobutton (Theo điểm, Theo Họ tên). Khi nhấn button "Sắp xếp", tùy theo người dùng chọn sắp xếp theo điểm hay sắp xếp theo Họ tên, sắp xếp lại 2 Listbox theo yêu cầu.
Bài 5 :
- Tương tự bài 4 nhưng thêm các chức năng sau: Thêm 2 button: Save và Load.
- Save: Lưu dữ liệu (Họ tên và Điểm của sinh viên) vào file .xlsx.
- Load: Đọc dữ liệu đã lưu trước đó và hiển thị lên Listbox.
Bài 7:
LẬP TRÌNH GIAO DIỆN C# CƠ BẢN: Serial Port
I. MỤC ĐÍCH YÊU CẦU:
- Phân tích yêu cầu, xây dựng giải thuật và viết code theo yêu cầu.
- Xây dựng những chương trình cơ bản bằng ngôn ngữ C/C++.
- Hình thành kỹ năng phát hiện và sửa lỗi khi lập trình.
II. HƯỚNG DẪN LÝ THUYẾT:
Thông thường, ta cần phải gửi và nhận thông tin từ một thiết bị khác có kết nối với máy tính của chúng ta (ví dụ một máy tính khác, một Card điều khiển hay đơn giản là truyền nhận dữ liệu với vi điều khiển). Trong phần này sẽ giới thiệu cách truyền nhận dữ liệu giữa máy tính và một thiết bị khác thông qua cổng giao tiếp COM với kiểu truyền dữ liệu nối tiếp (serial).
Lưu ý : Để truyền nhận dữ liệu thông qua cổng COM thì máy tính phải có cổng giao tiếp COM. Trong trường hợp máy tính không có cổng COM, chúng ta có thể chuyển đổi cổng USB sang cổng COM nhờ thiết bị (cáp) USB to COM. Sau khi cài Driver và kết nối Cáp USB to COM với máy tính thông qua cổng USB, máy tính sự tự động nhận và hiển thị cổng kết nối tương ứng (Xem trong Computer->Device Manager->Port(Com&LPT).Trong trường hợp không có cáp chuyển, chúng ta có thể dung phần mềm giả lập (Eltima Serial Port Monitor).
Trong Visual Studio, đối tượng cho phép chúng ta truyền nhận dữ liệu thông qua cổng COM là SerialPort.
Với SerialPort ta cần quan tâm đến các thuộc tính thường dùng sau:
Name: Tên gọi của SerialPort nhằm mục đích phân biệt với các đối tượng khác.
PortName: Có kiểu dữ liệu String, tên gọi của cổng COM sẽ dùng để kết nối (chúng ta có thể xem các cổng COM trong Device Manager
BaudRate: Tốc độ truyền dữ liệu. Khi truyền dữ liệu thì tốc độ truyền dữ liệu của thiết bị truyền và thiết bị nhận phải bằng nhau.
DataBits: Số lượng bit dữ liệu (bit Data) được truyền đi trong 1 gói truyền (package).
Parity: thuộc tính quy định cách thức kiểm tra chẵn lẻ (Parity) trong khi truyền.
StopBits: Quy định độ rộng của Stop Bit, có 3 giá trị là bằng 1, 1.5 và 2 so với độ rộng của bit data.
Open(): Lệnh mở Port. Trước khi truyền hay nhận dữ liệu thì phải mở Port và chỉ mở Port 1 lần duy nhất.
Close(): Lệnh đóng Port. Lưu ý là chỉ được đóng những Port đã mở trước đó.
Write(): Lệnh truyền dữ liệu.
Read(): Lệnh đọc dữ liệu.
ReadExisting(): Lệnh đọc toàn bộ dữ liệu chứa trong Buffer.
Lưu ý : Khi truyền dữ liệu từ máy tính A (hoặc từ Vi điều khiển) sang máy tính B, dữ liệu sẽ lần lượt được chép vào trong bộ nhớ đệm Buffer của SerialPort. Chẳng hạn khi ta truyền chuỗi “35” 3 lần thì trong buffer sẽ nhận được chuỗi “353535” (3 số 35 viết liên tiếp nhau). Khi chúng ta gọi lệnh ReadExisting() thì lệnh này sẽ đọc toàn bộ chuỗi đang chứa trong buffer đồng thời xóa Buffer. Do đó khi truyền dữ liệu để tránh tình trạng truyền nhiều lần mới đọc 1 lần thì khi truyền ta thêm 1 kí tự đặc biệt (chẳng hạn “*”) sau mỗi chuỗi truyền đi (ví dụ thay vì truyền chuỗi “35” thì ta truyền “35*”); nhờ vậy mà ta có thể phân biệt được dữ liệu nếu truyền nhiều lần (chuỗi nhận được ứng với 3 lần truyền là
“35*35*35*”).
2.1. Serial Port trong Visual Studio:
Trong Visual Studio, đối tượng cho phép chúng ta truyền nhận dữ liệu thông qua cổng COM là SerialPort. Thư viện quản lý serial port là thư viện IO, do đó khi muốn sử dụng serial port để truyền nhận dữ liệu, cần khai báo thêm dòng lệnh sau ở đầu chương trình:
using System.IO;
- Bước đầu tiên trong quá trình truyền/nhận dữ liệu với Serial Port là cài đặt các thông số truyền nhận. Các thông số truyền nhận bao gồm: PortName, BaudRate, Databits, Stopbits, Parity.
VD:
A.PortName = "COM6";
A.BaudRate = 9600;
A.DataBits = 8;
A.Parity = System.IO.Ports.Parity.None;
A.StopBits = System.IO.Ports.StopBits.One;
- Sau khi cài đặt thông số, trước khi truyền/nhận dữ liệu, cần phải mở Port.
+ Kiểm tra trạng thái Port và mở Port:
if(A.IsOpen == false) A.Open();
+ Truyền dữ liệu:
if(A.IsOpen == true) A.WriteLine("10");
+ Nhận dữ liệu:
string x = A.ReadExisting(); //String là kiểu chuỗi kí tự
Lưu ý : Muốn truyền nhận dữ liệu, cần phải mở port bằng lệnh Open(). Và chỉ được mở port 1 lần (nếu Port đã mở thì không được gọi lệnh Open() để mở port nữa). Ngoài ra, việc thiết lập các thông số truyền nhận phải được thực hiện khi Port đang đóng.
VD1 : Chương trình truyền nhận dữ liệu đơn giản
Bây giờ chúng ta sẽ xây dựng một chương trình truyền nhận dữ liệu đơn giản với một thiết bị khác (ví dụ như một máy tính khác) thông qua cổng COM nhờ cáp chuyển USB.COM (hoặc có thể dùng phần mềm giả lập):
Tạo một project mới dạng Windows Form và thiết kế giao diện như sau:
- ComboBox (CB1): Hiển thị những cổng COM hiện có của máy tính.
- Button Connect: khi nhấn Connect thì sẽ mở cổng COM chọn trong ComboBox, đồng thời chuyển thuộc tính Text của Button này thành Disconnect. Khi nhấn Disconnect thì sẽ đóng cổng Com đã mở.
- Khi nhấn Send: gửi dữ liệu trong Textbox TB1 ra cổng COM.
- Khi nhấn Receive: nhận dữ liệu từ Buffer và hiển thị lên Textbox TB2.
- Chọn đối tượng SerialPort trong toolbox và thêm vào Form, đặt tên là SP1.
Code của chương trình:
Click vào Form và chọn sự kiện Load, double click vào sự kiện Load để gọi delegate tương ứng:
private: System.Void Form_Load(System.Object^ sender, System.EventArgs e) { string [] A = SP1.GetPortNames(); //Đọc tất cả các Port đang có.
for (int i = 0;i<A.Length;i++)
CB1.Items.Add(A[i]);
}
Double click vào button Connect để gọi delegate tương ứng:
private: System.Void button1_Click(System.Object^ sender, System.EventArgs e) { if(button1.Text == “Connect”)
{
SP1.PortName = Convert.ToString(CB1.SelectedItem);
if (!SP1.IsOpen) //Chỉ mở Port khi Port đang đóng.
SP1.Open();
button1.Text = “Disconnect”;
}
if(button1.Text == “Disconnect”) {
SP1.PortName = Convert.ToString(CB1.SelectedItem);
if (SP1.IsOpen) //Chỉ đóng Port khi Port đã được mở.
SP1.Close();
button1.Text = “Connect”;
} }
Double click vào button Send để gọi delegate tương ứng:
private: System.Void button2_Click(System.Object sender, System.EventArgs e) { if (SP1.IsOpen) //Chỉ gửi dữ liệu khi Port đã mở
SP1.Write(TB1.Text);
}
Double click vào button Receive để gọi delegate tương ứng:
private: System.Void button3_Click(System.Object sender, System.EventArgs e) { if (SP1.IsOpen) //Chỉ nhận dữ liệu khi Port đã mở
TB2.Text = SP1.ReadExisting();
}