|
จดหมายเวียน หรือ Mail Merge คือการทำจดหมายหลายๆฉบับ โดยมีเนื้อความเหมือนกัน แต่มีชื่อและที่อยู่ของผู้รับที่ไม่เหมือนกันเท่านั้น ซึ่งแทนที่จะต้องพิมพ์จดหมายแต่ละฉบับสำหรับผู้รับแต่ละราย ก็เพียงแต่สร้างไฟล์ที่เก็บชื่อและที่อยู่ไว้ก่อน และสร้างไฟล์ที่เก็บข้อความในจดหมายไว้อีกไฟล์หนึ่งแยกจากกัน แล้วจึงนำข้อมูลทั้งสองไปรวมหรือผนวกกัน ... โค้ดชุดนี้จะใช้ VB.NET เป็นพระเอกในการควบคุมการทำงานของโปรแกรม เพื่อให้สามารถเลือกพิมพ์รายการที่ต้องการ หรือ พิมพ์ออกไปได้ทั้งหมดพร้อมกัน โดยใช้ฐานข้อมูล MS Access เก็บรายการลูกค้า/สมาชิก และใช้ของฟรี Syncfusion.DocIO เป็นตัวกลางในการสร้างจดหมายเวียน เพื่อส่งออกไปแสดงผลยัง MS Word ...
ดาวน์โหลดของฟรี Syncfusion Community License ...
ขั้นตอนการทำเอกสารจดหมายเวียน (Mail Merge) บน MS Word ...
- เลือก Data Source
- เบราซ์หาไฟล์ฐานข้อมูล
- การสร้าง Merge Field
- การสร้างกลุ่มการแสดงผล (BeginGroup) เพื่อแสดงผลตามรายการที่เลือกมาพิมพ์ (เริ่มจาก Insert Tab)
- การปิดกลุ่มการแสดงผล ... ทำเหมือนกับ BeginGroup แต่เปลี่ยนชื่อเป็น EndGroup
- การบันทึกไฟล์ต้นแบบ (Template) เพื่อนำไปใช้งานใน VB.NET
Add References ... Syncfusion.DocIO.Base.DLL
มาดูโค้ดต้นฉบับกันเถอะ ...
- Imports System.Data
- Imports System.Data.OleDb
- Imports Syncfusion.DocIO
- Imports Syncfusion.DocIO.DLS
- Public Class frmMailMerge
- '// Declare variable one time but use many times.
- Dim Conn As OleDbConnection
- Dim Cmd As OleDbCommand
- Dim DS As DataSet
- Dim DR As OleDbDataReader
- Dim DA As OleDbDataAdapter
- Dim strSQL As String '// Major SQL
- Dim MyPath As String = GetPath(Application.StartupPath)
- Private Sub frmMailMerge_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
- Me.Dispose()
- GC.SuppressFinalize(Me)
- Application.Exit()
- End Sub
- '// Start Here.
- Private Sub frmMailMerge_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
- '// Create MailMerge Folder if doesn't exist. (Keep Output Mail Merge.)
- If (Not System.IO.Directory.Exists(MyPath & "MailMerge")) Then System.IO.Directory.CreateDirectory(MyPath & "MailMerge")
- '//
- If Not ConnectDataBase() Then Me.Close()
- Call SetupDGVData(dgvData)
- Call RetrieveData()
- End Sub
- Private Function ConnectDataBase() As Boolean
- Try
- Dim strConn As String = _
- "Provider = Microsoft.ACE.OLEDB.12.0; " & _
- "Data Source = " & MyPath & "SampleDB.accdb"
- Conn = New OleDb.OleDbConnection(strConn)
- Conn.Open()
- If Conn.State = ConnectionState.Open Then Conn.Close()
- ' Return
- Return True
- Catch ex As Exception
- MessageBox.Show(ex.Message)
- Return False
- End Try
- End Function
- Public Function GetPath(ByVal MyPath As String) As String
- '/ Replace folder.
- MyPath = MyPath.ToLower.Trim.Replace("\bin\debug", "").Replace("\bin\release", "")
- '// If not found folder then put the \ (BackSlash ASCII Code = 92) at the end.
- If Microsoft.VisualBasic.Right(MyPath, 1) <> Chr(92) Then MyPath = MyPath & Chr(92)
- Return MyPath
- End Function 'GetPath
- ' / --------------------------------------------------------------------------------
- Private Sub RetrieveData()
- strSQL = _
- " SELECT Customer.CustomerPK, Customer.CustomerID, Customer.FullName, Customer.Address, Customer.Amphur, Province.ProvinceName, Customer.PostCode " & _
- " FROM Customer INNER JOIN Province ON Customer.ProvinceFK = Province.ProvincePK ORDER BY CustomerPK "
- Try
- If Conn.State = ConnectionState.Closed Then Conn.Open()
- Cmd = New OleDbCommand
- With Cmd
- .Connection = Conn
- .CommandText = strSQL
- End With
- DR = Cmd.ExecuteReader
- Dim i As Long = dgvData.RowCount
- While DR.Read
- With dgvData
- .Rows.Add(i)
- .Rows(i).Cells(0).Value = DR.Item("CustomerPK").ToString
- .Rows(i).Cells(1).Value = DR.Item("Fullname").ToString
- .Rows(i).Cells(2).Value = DR.Item("Address").ToString
- .Rows(i).Cells(3).Value = DR.Item("Amphur").ToString
- .Rows(i).Cells(4).Value = DR.Item("ProvinceName").ToString
- .Rows(i).Cells(5).Value = DR.Item("PostCode").ToString
- End With
- i += 1
- End While
- lblRecordCount.Text = "[Total : " & dgvData.RowCount & " records]"
- DR.Close()
- Cmd.Dispose()
- Conn.Close()
- Catch ex As Exception
- MessageBox.Show(ex.Message)
- End Try
- End Sub
- ' / --------------------------------------------------------------------------------
- '// Initialize DataGridView @Run Time
- Private Sub SetupDGVData(ByRef DGV As DataGridView)
- With dgvData
- .RowHeadersVisible = False
- .AllowUserToAddRows = False
- .AllowUserToDeleteRows = False
- .AllowUserToResizeRows = False
- .MultiSelect = False
- .SelectionMode = DataGridViewSelectionMode.FullRowSelect
- .ReadOnly = True
- .Font = New Font("Tahoma", 9)
- ' Columns Specified
- .Columns.Add("CustomerPK", "CustomerPK")
- .Columns.Add("Fullname", "Full Name")
- .Columns.Add("Address", "Address")
- .Columns.Add("Amphur", "Amphur")
- .Columns.Add("ProvinceName", "Province Name")
- .Columns.Add("PostCode", "PostCode")
- '// Select Print.
- Dim chkPrint As New DataGridViewCheckBoxColumn
- .Columns.Add(chkPrint)
- chkPrint.HeaderText = "Select Print"
- chkPrint.Name = "chkPrint"
- With .Columns("chkPrint")
- .HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
- .DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
- End With
- '// Hidden Columns
- .Columns(0).Visible = False
- ' Autosize Column
- .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
- '.AutoResizeColumns()
- '// Even-Odd Color
- .AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue
- ' Adjust Header Styles
- With .ColumnHeadersDefaultCellStyle
- .BackColor = Color.Navy
- .ForeColor = Color.Black ' Color.White
- .Font = New Font("Tahoma", 9, FontStyle.Bold)
- End With
- End With
- End Sub
- '// Toggle Checked Or UnChecked.
- Private Sub dgvData_CellContentClick(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvData.CellContentClick
- '// Column Index = 6
- If dgvData.Columns(e.ColumnIndex).Name = "chkPrint" Then
- Dim isChecked As Boolean = dgvData.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
- If isChecked = False Then
- dgvData.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = True
- Else
- dgvData.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = False
- End If
- End If
- End Sub
- '// Get DataTable.
- Private Function GetDataTable(ByVal Sql As String) As DataTable
- DS = New DataSet
- If Conn.State = ConnectionState.Closed Then Conn.Open()
- DA = New OleDbDataAdapter(Sql, Conn)
- DA.Fill(DS)
- DA.Dispose()
- Conn.Close()
- Dim table As System.Data.DataTable = DS.Tables(0)
- '// Sets table name as Customers for template merge field reference.
- table.TableName = "Customer"
- Return table
- End Function
- '// Print All Customers.
- Private Sub btnMailAll_Click(sender As System.Object, e As System.EventArgs) Handles btnMailAll.Click
- Dim document As New WordDocument(MyPath & "Template" & "GroupCustomer.docx")
- '/ Gets the data table
- Dim table As DataTable = GetDataTable("SELECT * FROM Customer ORDER BY CustomerPK")
- '/ Executes Mail Merge with groups
- document.MailMerge.ExecuteGroup(table)
- '/ Saves and closes the WordDocument instance
- '/ Folder--> ProjectName\Document
- Dim dtFileName As String = Format(Now, "ddMMyyyy-hhmmss")
- document.Save(MyPath & "MailMerge" & dtFileName & ".docx")
- document.Close()
- '// Open MS Word with Mail Merge.
- Process.Start(MyPath & "MailMerge" & dtFileName & ".docx")
- End Sub
- '// Print Only Select Customers.
- Private Sub btnMailSelect_Click(sender As System.Object, e As System.EventArgs) Handles btnMailSelect.Click
- Dim chkCount As Integer
- Dim Customers As New List(Of Customer)()
- For i = 0 To dgvData.RowCount - 1
- If CType(dgvData.Rows(i).Cells(6).Value, Boolean) = True Then
- chkCount += 1
- '// Keep data for print into Customer List. (CustomerPK, Fullname)
- Customers.Add(New Customer(dgvData.Rows(i).Cells(0).Value, dgvData.Rows(i).Cells(1).Value.ToString))
- End If
- Next
- '// Start Print.
- If chkCount = 0 Then
- MessageBox.Show("คุณไม่ได้เลือกทำรายการพิมพ์", "รายงานสถานะ", MessageBoxButtons.OK, MessageBoxIcon.Information)
- Return
- '// Print only the selected columns.
- Else
- Dim document As New WordDocument(MyPath & "Template" & "GroupCustomer.docx")
- Dim table As New MailMergeDataTable("Customer", Customers)
- document.MailMerge.ExecuteGroup(table)
- '/ Folder--> ProjectName\MailMerge
- Dim dtFileName As String = Format(Now, "ddMMyyyy-hhmmss")
- document.Save(MyPath & "MailMerge" & dtFileName & ".docx", FormatType.Docx)
- document.Close()
- Process.Start(MyPath & "MailMerge" & dtFileName & ".docx")
- End If
- '// Clear Selection
- For i = 0 To dgvData.RowCount - 1
- If CType(dgvData.Rows(i).Cells(6).Value, Boolean) = True Then
- dgvData.Rows(i).Cells(6).Value = False
- End If
- Next
- End Sub
- End Class
คัดลอกไปที่คลิปบอร์ด
ส่วนของ Customer Class เพื่อส่งไปให้กับ Array List เก็บรายการที่ต้องการพิมพ์จดหมายเวียน ...
- Public Class Customer
- Private m_CustomerPK As Long
- Public Property CustomerPK() As Long
- Get
- Return m_CustomerPK
- End Get
- Set(ByVal value As Long)
- m_CustomerPK = value
- End Set
- End Property
- Private m_CustomerID As String
- Public Property CustomerID() As String
- Get
- Return m_CustomerID
- End Get
- Set(value As String)
- m_CustomerID = value
- End Set
- End Property
- Private m_Fullname As String
- Public Property Fullname() As String
- Get
- Return m_Fullname
- End Get
- Set(value As String)
- m_Fullname = value
- End Set
- End Property
- Private m_Address As String
- Public Property Address() As String
- Get
- Return m_Address
- End Get
- Set(ByVal value As String)
- m_Address = value
- End Set
- End Property
- Private m_ProvinceName As String
- Public Property ProvinceName() As String
- Get
- Return m_ProvinceName
- End Get
- Set(ByVal value As String)
- m_ProvinceName = value
- End Set
- End Property
- Private m_PostCode As String
- Public Property PostCode() As String
- Get
- Return m_PostCode
- End Get
- Set(ByVal value As String)
- m_PostCode = value
- End Set
- End Property
- Private m_PictureName As String
- Public Property PictureName() As String
- Get
- Return m_PictureName
- End Get
- Set(ByVal value As String)
- m_PictureName = value
- End Set
- End Property
- '// หากต้องการใช้งานฟิลด์อื่นๆ ต้องเพิ่มเข้ามาต่อท้ายในส่วนนี้ด้วย
- Public Sub New(CustomerPK As Integer, Fullname As String)
- Me.CustomerPK = CustomerPK
- Me.Fullname = Fullname
- End Sub
- End Class
คัดลอกไปที่คลิปบอร์ด
ดาวน์โหลดโค้ดฉบับเต็ม VB.NET (2010) ได้ที่นี่ ...
|
ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง
คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน
x
|