PDA

View Full Version : Office VBA, mỗi ngày một ví dụ....



paulsteigel
10-03-2005, 19:33
Vâng!
Thưa các Quý vị, vào ddth tôi thấy nhiều câu hỏi về Office VBA quá, quả thật cũng có khá nhiều người như tôi vẫn đang mò mẫm về Access, Excel... để làm các ứng dụng của mình vì mục đích nào đó - cho mình hoặc cho người khác...
Thiết nghĩ chúng ta có thể bắt đầu một chủ đề mới chuyên về Office VBA nhé, mỗi ngày một ví dụ mới về các thủ thuật.
Nếu Quý vị đồng ý thì chúng ta cùng đóng góp để tất cả đều có thể bắt đầu học từ nhau những điều mình chưa biết để công việc sẽ ngày càng tiến triển...
Nói thế thôi vậy không thì lại bảo là nhiều lời.
'//////////Now...Start.......
Hôm nay tôi bắt đầu với việc đưa thêm các mục menu mới vào Excel và tự động xoá khi thoát khỏi Excel nhé....
' Đoạn mã sau đây sẽ tạo ra một thực đơn mới trong thực đơn hệ thống của Excel, đồng thời tạo ra một thực đơn thấp hơn, khi nhấn vào sẽ thực thi một động tác ta quy định....
Chép đoạn mã nguồn sau vào Code Module của Thisworkbook nhé
'================================================
Option Explicit

Private Sub Workbook_Open()
' Để tạo được thực đơn, bạn phải tham chiếu đến thư viện đối tượng của
' Office - nhấn Tools chọn Reference và tìm thư viện đối tượng của Office

Dim icmb As CommandBar
Dim cbCtrPar As CommandBarControl, cbCtrChild As CommandBarControl
Set icmb = Application.CommandBars("Worksheet Menu Bar")

' Đoạn này tớ làm để tắt thực đơn hệ thống mà thôi... nay chẳng dùng nữa
'For Each cbCtrPar In iCmb.Controls
' cbCtrPar.Visible = False
'Next

' Bắt đầu nhé
Set cbCtrPar = icmb.Controls.Add(msoControlPopup, , , , True)
' Đặt tên và gán đuôi cho thực đơn...
cbCtrPar.Caption = "Test"
cbCtrPar.Tag = "Created"

' Tạo thực đơn con cho thực đơn trên
Set cbCtrChild = cbCtrPar.Controls.Add(msoControlButton, 2091, , , True)

' Gán đuôi Tagf cho thực đơn để sử dụng sau này....
cbCtrChild.Tag = "Created"
' Bây giờ gán hành động cho thực đơn đây (ta phải có một hàm trong module mới được, nếu không, thì nó chẳng chạy đâu.
cbCtrChild.OnAction = "AssignmeNow"
cbCtrChild.Caption = "Okay here is the test"
Set icmb = Nothing
Set cbCtrPar = Nothing
End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)
' Thủ tục này sẽ được kích hoạt khi đóng tài liệu, thực ra khi Excel thoát ra
' thực đơn vừa tạo sẽ bị xoá do ta đặt thuộc tính Temporary là true lúc
' tạo thực đơn ở phần trên
Dim cbCtrPar As CommandBarControl
Dim icmb As CommandBar
' Okay - ta phải tìm cái thực đơn vừa tạo và xoá nó nhé, bí quyết là
' thuộc tính tag ta đã đặt từ khi tạo thực đơn
Set icmb = Application.CommandBars("Worksheet Menu Bar")

'On Error Resume Next
For Each cbCtrPar In icmb.Controls
If cbCtrPar.Tag = "Created" Then
cbCtrPar.Delete
Exit For
End If
Next
' đoạn này để bật thực đơn hệ thống lại - nay cũng không dùng , hihi
'For Each cbCtrPar In iCmb.Controls
' cbCtrPar.Visible = true
'Next

Set cbCtrPar = Nothing
End Sub

'///////////////////Đưa đoạn code này vào một Module mới nhé/////////
Function AssignmeNow()
MsgBox "Hello Dear"
End Function

paulsteigel
11-03-2005, 14:09
Ngại viết lại quá... Cái này dùng để in ra danh sách các số ID của Menubar trong Excel...

Sub GetBtnID()
Dim cmb As Object
Dim iStr As String
'' search through all commanbars...
For Each cmb In Application.CommandBars
iStr = iStr & PrintBtnID(cmb)
Next
WriteLog iStr
End Sub

Private Function PrintBtnID(iCb As Object) As String
Dim iCtr As Object
Dim RetStr As String
For Each iCtr In iCb.Controls
If hasSubControl(iCtr) Then
'' recursive search as button may contain sub-control as well
PrintBtnID = PrintBtnID & PrintBtnID(iCtr)
Else
RetStr = RetStr & iCtr.Caption & vbTab & iCtr.ID & vbCrLf
End If
Next
PrintBtnID = RetStr
End Function

Private Sub WriteLog(iTxt As String)
'' write all to a file...
Dim txtString As String, FileNames As String
FileNames = ThisWorkbook.Path & "\IDNumber.log"
On Error GoTo ErrorChk
Open FileNames For Append As #1
Print #1, iTxt
Close #1
Exit Sub
ErrorChk:
Close #1
End Sub

Private Function hasSubControl(iCtr As Object) As Boolean
Dim i As Long
On Error GoTo ErrHandler
i = iCtr.Controls.Count
hasSubControl = True
ErrHandler:
End Function

enemykill
11-03-2005, 18:51
Hi bác,

Bài viết hay đấy, vì tớ ít nghiên cứu excel nên có nhiều điều để hỏi.

Trong excel tạo một form+ list box.
Tôi muốn lấy dữ liệu bên ngoài ví dụ một tập tin excel khác rồi đưa dữ liệu đó vào listbox của form. Tôi biết nó dùng ado để lấy dữ liệu. Ngặc một nổi phần help của excel không có hướng dẫn lấy dữ liệu từ bên ngoài mà chỉ trong book của excel mà thôi.

Nếu bác biết hãy chia sẽ cùng anh em.

Cám ơn bác nhiều.

paulsteigel
11-03-2005, 19:57
Ờ ờ.... cái này thì được....
+ Nếu bạn lấy dữ liệu từ file excel khác thì dễ quá..
Đơn giản là thiết lập một kết nối với file Excel đó, xong đó là đọc các range của nó như là file excel bạn đang làm việc vậy....
Ví dụ đây

Option Explicit
' Add a listbox name listbox1 into the form, create an excel file with the sheet 1, a header row of Mynam and add some text there.

Private Sub UserForm_Initialize()
'AddFirstWay ' user internal excel connection
AddSecondWay ' user DAO connection, you have to set reference to DAO 3.***
End Sub

Private Sub AddFirstWay()
' Okay connect the to other datasource here
Dim Wrk As Workbook
Dim wrsht As Worksheet
' assuming that data is in sheet1 of the workbook test
' in the same folder with current workbook
Set Wrk = Workbooks.Open(ThisWorkbook.Path & "\Test.xls")
Set wrsht = Wrk.Sheets("Sheet1")

' Initialize a range now
Dim iRange As Range
Dim curRange As Range
Dim i As Long
Set curRange = wrsht.Range("B2")
While Not IsEmpty(curRange.Value)
ListBox1.AddItem (curRange.Value)
Set curRange = curRange.Offset(1)
Wend
Set curRange = Nothing
Set wrsht = Nothing
Wrk.Close
End Sub

Private Sub AddSecondWay()
' We use DAO Connection
Dim dbs As Database
Dim rcs As Recordset

' Initial the database object
Set dbs = OpenDatabase(ThisWorkbook.Path & "\Test.xls", False, False, "Excel 8.0;HDR=YES;")
'Dim iB As Object
'For Each iB In dbs.TableDefs
' Debug.Print iB.Name
'Next
' Now open the sheet
Set rcs = dbs.OpenRecordset("SELECT [MyName] FROM [Sheet1$] where [MyName]<>'' Order by [MyName];")
' Add record to list
While Not rcs.EOF
ListBox1.AddItem (rcs.Fields("MyName"))
rcs.MoveNext
Wend
rcs.Close
dbs.Close
End Sub

enemykill
13-03-2005, 10:03
Bác lấy đâu cuốn sách đó vậy,

Hay đó.

Nhưng chỉ có thể đưa một column vào thôi.
tôi nghĩ thế này
' lay du lieu dua vao cot thu hai trong listbox

me.listbox1.list(0,1)= rcs.Fields("MyName1"))

MyName1 la lay trong sql field thu hai, dua vao no khong loop duoc day.
ma khong co additem thi khng run duoc.

Co cach nao duoc n cot vao listbox khong

thanks bác rất nhiều nhiều

haule_nth
13-03-2005, 10:09
Cái này hay đó, pác post nhiều nhiều lên 1 tí cho anh em học hỏi đi

paulsteigel
13-03-2005, 10:40
Thành thực xin lỗi quý vị, những cái này tôi đều lấy từ kinh nghiệm làm việc trước đây mà thôi cũng như từ một vài câu hỏi mà các bạn ở ttvnol cũng như ở đây đặt ra.
Tuy nhiên có điều là tôi chỉ là dân Amateur nên việc trình bày các đoạn thủ tục đều không chuyên nghiệp ... hihi. Và biết đến đâu thì nói mò đến đó thôi.
(VBA là cái mà tôi thích nhất)
Vì thế, nếu có nhiều câu hỏi thì tôi sẽ lựa chọn và trả lời từng phần...
Trở lại vấn đề của enemykill....

"Nhưng chỉ có thể đưa một column vào thôi.
tôi nghĩ thế này
' lay du lieu dua vao cot thu hai trong listbox

me.listbox1.list(0,1)= rcs.Fields("MyName1"))"
' Với cách lấy trực tiếp từ range trong excel thì thế này
ListBox1.ColumnCount = 4
ListBox1.RowSource = "a1:d4"

Còn lấy theo cách dùng DAO hoặc ADODB thì có khác tí tẹo, tôi không nói lại cách lấy dữ liệu nhé, chỉ đưa ra đây cách để làm thế nào điền dữ liệu vào listbox có nhiều cột một cách đơn giản nhất:

Private Sub Testmulticolumn()
'In: Just load data to a sample multi-dimension array...
'out: set the list() property to the data charged array...

Dim i, j, Rows As Single
' We have to be sure in advance how many columns should be added to the list (as we can only redeclare the second dimension of the array)
Dim MyArray(2, 3) As String
' How many column, the list should have
ListBox1.ColumnCount = 3
' this is to decide widths of colums in listbox
ListBox1.ColumnWidths = "1 in;1 in;1 in"
' let's assuming that we have only 2 rows for fun...
Rows = 2
' looping for adding data to the array
For j = 0 To ListBox1.ColumnCount - 1
For i = 0 To Rows - 1
MyArray(i, j) = "Row " & i & ", Column " & j
Next i
Next j
'Load MyArray into ListBox1
ListBox1.List() = MyArray
End Sub
' Cám ơn sự theo dõi của các quý vị...
<<<<Quả thật mình không thích dịch lại cái comment vì trong IDE của VBA mình đánh tiếng việt Unicode không được nên dùng luôn tiếng ANh cho tiện, nếu các bạn không thích thì cho tôi biết một tiếng để lần sau không làm thế nữa ạ...??>>>>

paulsteigel
15-03-2005, 09:26
Vâng bây giờ là phần chuyển đổi bảng mã...
Tớ đã làm một công cụ chuyển đổi nhúng trong word hỗ trợ 17 bảng mã khác nhau, khá to, 250 KB, bận quá không làm tiếp được, nếu ai quan tâm muốn cùng đóng góp tiếp thì mail cho tớ.
Bây giờ tớ chỉ đưa ra một công cụ chuyển đổi mã tcvn sang Unicode và ngược lại thôi (Cắt bớt chỉ làm việc với 75 nguyên âm mà tcvn có thôi)
Không giải thích nhiều lắm ....
Function ToUnicode(txtString As String, Optional isReversed As Boolean = False) As String
' This function will do the conversion of text string into unicode
Dim iStr As String, repTxt As String, mText As String
Dim i As Long, j As Long
Dim iUnicode As Variant ' array to keep unicode char set
Dim iTCVN As Variant ' array to keep TCVN char set
Dim iProcList() As String ' array to keep what to convert

'parse the parameter into this local variable
iStr = txtString
mText = txtString

If fLang = "E" Then GoTo fExit
iUnicode = Array(225, 224, 7843, 227, 7841, 259, 7855, 7857, 7859, 7861, 7863, 226, _
7845, 7847, 7849, 7851, 7853, 233, 232, 7867, 7869, 7865, 234, 7871, 7873, 7875, _
7877, 7879, 237, 236, 7881, 297, 7883, 243, 242, 7887, 245, 7885, 244, 7889, 7891, _
7893, 7895, 7897, 417, 7899, 7901, 7903, 7905, 7907, 250, 249, 7911, 361, 7909, _
432, 7913, 7915, 7917, 7919, 7921, 253, 7923, 7927, 7929, 7925, 273, 193, 192, 195, _
258, 194, 212, 416, 431, 272)

iTCVN = Array(184, 181, 182, 183, 185, 168, 190, 187, 188, 189, 198, 169, 202, 199, 200, _
201, 203, 208, 204, 206, 207, 209, 170, 213, 210, 211, 212, 214, 221, 215, 216, 220, _
222, 227, 223, 225, 226, 228, 171, 232, 229, 230, 231, 233, 172, 237, 234, 235, 236, _
238, 243, 239, 241, 242, 244, 173, 248, 245, 246, 247, 249, 253, 250, 251, 252, 254, _
174, 193, 192, 195, 161, 162, 164, 165, 166, 167)

' Re-enlarge the array
ReDim iProcList(1, 133)
' process the vowel only and convert to asc code
For i = 1 To Len(mText)
repTxt = Mid(mText, i, 1)
If AscW(repTxt) > 122 Then
iStr = Replace(iStr, repTxt, "[" & AscW(repTxt) & "]")
mText = Replace(mText, repTxt, " ")
' write the processed list
iProcList(1, j) = "[" & AscW(repTxt) & "]"
If isReversed Then
iProcList(0, j) = GetElementNo(AscW(repTxt), iUnicode)
Else
iProcList(0, j) = GetElementNo(AscW(repTxt), iTCVN)
End If
j = j + 1
End If
Next
If j = 0 Then
ToUnicode = txtString
Exit Function
End If
ReDim Preserve iProcList(1, j - 1)
' now convert to unicode
For i = 0 To UBound(iProcList, 2)
If isReversed Then
iStr = Replace(iStr, iProcList(1, i), ChrW(iTCVN(Val(iProcList(0, i)))))
Else
iStr = Replace(iStr, iProcList(1, i), ChrW(iUnicode(Val(iProcList(0, i)))))
End If
Next
fExit:
ToUnicode = iStr
End Function

Private Function GetElementNo(iTxt As Long, iObj As Variant) As String
Dim i As Long
For i = 0 To UBound(iObj)
If iTxt = iObj(i) Then
GetElementNo = CStr(i)
Exit For
End If
Next
End Function

‘ đây cũng là một câu hỏi các bạn ở box khác đang hỏi, nên tiên đây tôi post luôn để đỡ phải trả lời nhiều .. hihi
Nay kính thư

paulsteigel
17-03-2005, 12:47
I. Trả lời câu hỏi của bạn Hùng
Tôi gửi kèm phần trả lời bạn hungdhb để mọi người tiện tham khảo cách kết nối với word bằng Access hoặc VB.

Cảm ơn bạn đã chỉ cho tôi giao tiếp VB và word.Tôi đã hiểu.Tôi đã làm theo bạn hướng dẫn.Khi chạy chương trình thì mỗi khi ghi data từ biến mystring vào word thì chương trình lại hỏi save as để mình phải nhập tên file cần lưu vào. Sau đó nó tự động đóng file đó lại và chỉ còn cửa sổ word trắng (không có file nào hiển thị cả). Tôi muốn mỗi khi chương trình ghi dữ liệu từ biến mystring vào file word, nó sẽ tự động lưu vào “C: \doc” với tên file là ngày giờ lúc đó kèm theo tên form hiện hành.Sau đó chương trình sẽ tự động mở file đó ra xem luôn. Nếu vậy thì tôi phải sửa ntn trong đoạn code đó, bạn giúp tôi với. Xin cảm ơn rất nhiều.
À, sao khi chạy tôi không thấy word tự động prỉnpiview cho mình thấy mặc dù mình đã có viết lệnh wrdDoc.PrintPreview

Option Explicit
Dim wrdApp As Word.Application
Dim wrdDoc As Word.Document
Public Sub WordAutomate()
'Dim wrdApp As Object
'Dim wrdDoc As Object
'Dim wrdSelection As word.Selection
Dim wrdSelection As Word.Selection
Dim myString As String
Set wrdApp = CreateObject("Word.application")

wrdApp.Visible = False
myString = "A test for word Automation"
Set wrdDoc = wrdApp.Documents.Add

wrdDoc.Select

Set wrdSelection = wrdApp.Selection
wrdSelection.TypeText myString
wrdDoc.PrintPreview
wrdDoc.Close

End Sub

'//////////////////////////////////////////////////////
' Create a form and three buttons
' Then you paste the following code.... all you will see
' Assuming that we are using access as the IDE.
Option Explicit
Dim wrdApp As Object
Dim wrdDoc As Object

Sub WordAutomate(TxtToInsert As String)
Dim wrdSelection As Object
Dim myString As String
Set wrdApp = CreateObject("Word.application")
wrdApp.Visible = True
Set wrdDoc = wrdApp.Documents.Add
wrdDoc.Select
Set wrdSelection = wrdApp.Selection
wrdSelection.Text = TxtToInsert
End Sub

Private Sub cmdClose_Click()
wrdDoc.SaveAs currentproject.Path & "\" & Me.Name & Format(Now, "dd_mm_yyyy") & ".doc"
wrdDoc.Close
Set wrdDoc = Nothing
wrdApp.quit
End Sub

Private Sub cmdOpen_Click()
WordAutomate "This is the test"
End Sub

Private Sub cmdPreview_Click()
wrdDoc.PrintPreview
End Sub
'//////////////////////////////////////////////////////
'Nay kính thư...

II. Cách tạo menubar trong access
Tạo menubar trong access là một công việc khá thú vị. Hiện tại theo tôi biết thì có 2 cách cơ bản để tạo ra menubar trong access.
+ Dùng Macro với Addmenuitem (tôi không dùng nữa vì cũng không thích cách này lắm)
+ Dùng Code. Tôi sẽ giới thiệu cách này, (các bạn nên xem ví dụ trong file access kèm theo nhé)
'////////////////////////////////////////
Bắt đầu:
+ Tạo ra bảng có chứa các menu mà ta định chế tác.
+ Thực thi đoạn mã tạo menu.
(Để có thêm chi tiết về bảng dữ liệu, các bạn download ví dụ về nhé)
Sub CreateMenubar()
' Tạo Toolbar
CreateMenubar "VDPToolBar", 0
' Tạo Menubar
CreateMenubar "VDP Man", , False
' Tạo PopMenu
CreateMenubar "VDPPop", 2
End sub

Private Sub CreateMenubar(mnuBar As String, Optional iType As Long = 1, Optional DontCreate As Boolean = True)
Dim i As Long
' Create menubar
Dim mnuRcs As Recordset
Dim iCmb As CommandBar
Dim cbCtrPar As Object
Dim cbCtrChild As CommandBarControl
' Start creating the menu
If Not DontCreate Then
Set iCmb = CommandBars.Add(Name:=mnuBar, Position:=IIf(iType = 2, msoBarPopup, msoBarTop), MenuBar:=IIf(iType = 0 Or iType = 2, False, True), Temporary:=False)
Else
Set iCmb = CommandBars(mnuBar)
End If

' Initialized recordset
Set mnuRcs = CurrentDb.OpenRecordset("Select * from SysMenu where MenubarName='" & mnuBar & "' And [Tag] is null Order by [Order];")

With mnuRcs
While Not .EOF
If IsNull(.Fields("BaseIndex")) Then
Set cbCtrPar = iCmb.Controls.Add(msoControlPopup, , , , False)
cbCtrPar.Caption = .Fields("MnuCaptionV")
cbCtrPar.Tag = .Fields("AccessLevel")
Else
If iType <> 1 Then Set cbCtrPar = CommandBars(mnuBar)
If .Fields("Action") = "import" Then
Set cbCtrChild = cbCtrPar.Controls.Add(msoControlButton, .Fields("SysMenuID"), , , False)
Else
Set cbCtrChild = cbCtrPar.Controls.Add(msoControlButton, , , , False)
If .Fields("Action") <> "" Then cbCtrChild.OnAction = .Fields("Action")
End If
cbCtrChild.Caption = .Fields("MnuCaptionV")
cbCtrChild.Tag = .Fields("AccessLevel")
cbCtrChild.BeginGroup = .Fields("Group")
' depend on type of bar, we can set the button face here
If iType = 0 Then
If Not IsNull(.Fields("SysMenuID")) Then
CommandBars(CStr(.Fields("SysMenu"))).Controls(.Fields("SysMenuID")).CopyFace
cbCtrChild.PasteFace
End If
cbCtrChild.Style = 3
End If
End If
.MoveNext
Wend
.Close
End With
If iType <> 2 Then
iCmb.Position = msoBarTop
iCmb.Protection = msoBarNoChangeVisible + msoBarNoCustomize + msoBarNoResize + msoBarNoChangeDock
iCmb.Visible = True
End If
Set iCmb = Nothing
Set cbCtrPar = Nothing
Set cbCtrChild = Nothing
End Sub

Function MenuBarExist(mnuBarName As String) As Boolean
' Cái này để xác định xem menubar có tồn tại không
Dim mnuBar As Object
' Check for wherether toolbar M is installed
For Each mnuBar In Application.CommandBars
If mnuBar.Name = mnuBarName Then
MenuBarExist = True
Exit Function
End If
Next
End Function

Sub SetAccesslevel(mnuBarName As String, iLevel As Integer)
Dim mnuBar As CommandBar
Set mnuBar = CommandBars(mnuBarName)
SetAccess mnuBar, iLevel
Set mnuBar = Nothing
End Sub

Private Sub SetAccess(Mnb As Object, iLevel As Integer)
' Cái này để hiển thị các menubar tại các mức truy cập khác nhau
Dim obj As Object
For Each obj In Mnb.Controls
If HasSubControl(obj) Then SetAccess obj, iLevel
If InStr(obj.Tag, CStr(iLevel)) <> 0 Then obj.Visible = True Else obj.Visible = False
Next
End Sub
' Nếu các bạn có yêu cầu gì thêm thì gửi thư cho tôi nhé. ngocdd@itprog.gov.vn

paulsteigel
18-03-2005, 09:04
Mỗi một tập tin mdb đều có một số thuộc tính đặc biệt, theo đó các thuộc tính này nếu được điều chỉnh sẽ mang lại một ảnh hưởng nhất định đến cách “cư xử” của tập tin, một số thuộc tính cơ bản loại này thường không thể tác động trước khi ta tiến hành thủ tục tạo lập nó. Sau đây là tên một số thuộc tính cơ bản (tôi tạm dich tên thuộc tính sau dấu”/”):
AppTitle / Tiêu đề của ứng dụng
AppIcon / Đường dẫn của biểu tượng
StartupShowDBWindow / Khi khởi thộng hiển thị cửa sổ Database
StartupShowStatusBar / Khi khởi động hiển thị thanh trạng thái
AllowShortcutMenus / Cho phép hiển thị thực đơn khi nhấn trái chuột
AllowFullMenus / Cho phép hiển thị tất cả các thực đơn
AllowBuiltInToolbars / Cho phép hiển thị các thanh công cụ hệ thống
AllowToolbarChanges / Cho phép thay đổi thanh công cụ
AllowBreakIntoCode / Cho phép xem mã nguồn
AllowSpecialKeys / Cho phép nhấn phím đặc biệt (F11/ Alt + F11...)
AllowBypassKey / Cho phép nhấn phím trượt
Riêng các thuộc tính 1 và 2 thì ta cần có kiểu dữ liệu truyền cho nó là ký tự còn các thuộc tính còn lại, tham số truyền vào chỉ là true hoặc false.
Sau đây là đoạn mã nguồn thực thi:
‘/////////////////////////////////////////
Sub SetStartupProperties()
‘ Tôi dùng trong hệ thống của mình một bảng cung cấp các giá trị thuộc tính cũng như tên thuộc tính/ để sử dụng được mã nguồn này, bạn nên tạo ra một bảng có cấu trúc trường như trong câu lệnh sql sau:
‘Create Table Config(ID Integer, PropertyName Text(150), PropertyValue Text(150), Type Integer);
‘Sau đó thêm các giá trị thuộc tính trên đây vào bảng này
Dim dbs As RecordSet
Const DB_Text As Long = 10
Const DB_Boolean As Long = 1
Set dbs = CurrentDb.OpenRecordset("Select * from Config Where [Type]=1")
' Việc này chỉ làm thay đổi thuộc tính của CSDL
While Not dbs.EOF
If dbs.Fields(1) = "AppIcon" Then
ChangeProperty dbs.Fields(1), DB_Text, CurrentProject.Path & "\" & dbs.Fields(2)
Else
ChangeProperty dbs.Fields(1), IIf(dbs.Fields(1) = "AppTitle", DB_Text, DB_Boolean), dbs.Fields(2)
End If
dbs.MoveNext
Wend
Application.RefreshTitleBar
dbs.Close
End Sub

Function ChangeProperty(strPropName As String, varPropType As Variant, varPropValue As Variant) As Integer
‘ Hàm này dùng để thay đổi giá trị thuộc tính, nếu gặp lỗi thì nó sẽ tạo ra thuộc tính của CSDL (vì trên thực tế thuộc tính này chưa được tạo ra)
Dim dbs As Object, prp As Variant
Const conPropNotFoundError = 3270

Set dbs = CurrentDb
On Error GoTo Change_Err
dbs.Properties(strPropName) = varPropValue
ChangeProperty = True

Change_Bye:
Exit Function

Change_Err:
If Err = conPropNotFoundError Then ' Không thấy thuộc tính này.
Set prp = dbs.CreateProperty(strPropName, _
varPropType, varPropValue)
dbs.Properties.Append prp
Resume Next
Else
' Lỗi không xác định được.
ChangeProperty = False
Resume Change_Bye
End If
End Function
‘ Bạn có thể dùng cách này để ngăn cản sự truy cập theo cách thông thường đến cơ sở dữ liệu của bạn. Tuy nhiên, một số thuộc tính chỉ thay đổi và kích hoạt sau lần khởi động thứ 2 của cơ sở dữ liệu.

paulsteigel
20-03-2005, 20:21
A. ///////////////////////////////Ngày hôm nay nhá///////////////////////////////
Mệt chưa nhỉ... chắc là chưa đâu quá....
Hôm nay tớ giới thiệu cho các bạn một cách sử dụng chính các công cụ của Word để tạo một công cụ chuyển đổi bảng mã một cách đơn giản. Về chủ đề này, tớ đã trình bày cách đây 4 năm rồi nhưng dù sao thì cũng có thể thích hợp với các bạn mới bắt đầu nhỉ.
(Hiện tại có nhiều cách chuyển đổi, chuyển đổi offline, online... chuyển đổi file rtf, htm....)
Bắt đầu:
1. Giải thích thế nào là chuyển đổi bảng mã:
Uh - chỉ là ánh xã các mã từ bảng này sang bảng kia thôi và thay thế:
ví dụ trong tcvn thì ký tự ® là chữ đ thì khi chuyển sang Unicode ta chỉ thay thế ® bằng chữ đ.
2. Lập danh sách mã nguyên âm cho tiếng việt với các bảng mã khác nhau số nguyên âm đã ghép dấu kế cả chữ hoa và thường trong tiếng Việt là 134...
Với mỗi loại mã thì số nguyên âm này có thể ít hơn (Tcvn chỉ có 77, VSCII cũng hơn một tý....)
Cái này dùng Vietkey - Unikey gõ vào là được hihi, thường người ta tuân thủ trật tự để tránh nhầm lẫn
á à ả ã ạ ....
3. Thiết kế thuật toán thay thế.
+ Thiết kế thuật toán lấy nội dung đoạn mã cần chuyển đổi. Cái này cũng đòi hỏi nhiều kỹ thuật, tuy nhiên nó phụ thuộc vào cách chuyển đổi.
+ Thiết kế thuật toán xử lý thay thế ký tự.
Cái này thì bạn có thể ghi một Macro bằng word sau đó sửa code theo ý của bạn.
4. Kết hợp với sáng kiến của bạn:
+ Trong word có nhiều ký tự điều khiển bị trùng lắp với ký tự của một số bảng mã. Do đó để tránh gây lỗi khi thao tác đối với các ký tự này, việc vận dụng kinh nghiệm vào việc chọn biện pháp xử lý chuỗi là rất quan trọng.
+ Một số bảng mã sử dụng ký tự lẫn nhau, do đó bạn cần chú ý để tránh thay thế 2 lần.
5. Cái này nhiều Bác còn đau đầu: Đoán mã của đoạn văn bản:
Có nhiều cách tiếp cận, mỗi cái có một lợi điểm song cái nào cũng không là tối ưu. Cái thì sử dụng bằng cách đoán phông chữ, cái thì so với ký tự mẫu ngẫu nhiên....
6. Trả lại định dạng văn bản gốc (phông tương đương...): Cái này cũng thế vì ta chẳng có chuẩn đặc biệt nào về phông chữ nên củ chuối lắm, ai bảo là sẽ chuyển đổi văn bản, giữ nguyên format là không đúng.
Để tiện cho các bạn tham khảo, tớ kèm theo đây là một công cụ chuyển đổi chưa hoàn chỉnh đã làm cách đây vài năm...
Nếu ai quan tâm thì có thể sửa đổi và post lại cho tuốt cả nhá.
Cách cài đặt:
Công cụ cài tự động, bạn cần phải bật chế độ Security của word về medium (đối với office 9.x trở lên)
Nếu chương trình được cài thành công thì nó sẽ tự động chép vào thư mục start up của word và đóng các tài liệu đang mở.
Nếu không thì cần kiểm tra xem bạn đã thực sự tạo điều kiện cho macro chạy chưa nhé.
(Chức năng đoán mã chạy không ổn lắm nên các bạn cần chú ý trước khi chuyển đổi)
Nay kính thư


B. ///////////////////////////////Ngày hôm trước nhá///////////////////////////////
À quên: Tiếp theo bài về cách tạo menu trong Access 2000, tôi giới thiệu cách dùng macro để tạo Menu nhá:
1. Tạo một Macro với tên là tên của menubar cần tạo:
Ví dụ Sysmenu (trong ví dụ kèm theo của tôi).
Trong Macro Sysmenu này có một loạt dòng lệnh Addmenu với phần:
Menu name: là tên của menu bạn cần hiển thị ví dụ File
Menu Macroname: mnuFiles tham chiếu đến tên macro sẽ dùng để tạo submenu cho cái File (tên macro là mnuFiles)...
Tương tự bạn làm nhiều cái như thế cho nhiều mục mennu
Tạo Menu File ở trên:
Nội dung của mnuFiles
Trong cái này nó có các cột là Macro name, condition, Action.
Tôi chỉ quan tâm đến Macroname và Action thôi nhá:
+ Macroname: bạn đưa vào tên của hành động định gán cho action (ví dụ Print preview chẳng hạn) Khi menu này chạy nó sẽ hiển thị là Printpreview.
+ Action: bạn bán hành động cho menu này ... có thể là runcommand/ open form... rất trực quan, bạn hoàn toàn có thể chọn hoặc cũng có thể gõ tên của tên thủ tục cần thực thi vào ... (chú ý nếu là gọi đến một code module thì bạn phải định nghĩa hành động dưới dạng hàm ví dụ: function PrintPreview().
và cứ thế làm bao nhiêu tuỳ thích ...
2. Để menu trên chạy - bạn chọn tool, start up và gõ vào mục menubar tên Sysmenu và đóng lại
KHởi động lại database xem nhá ....
Nếu không chạy tớ mời các bạn một chầu kẹo vừng và nước lã đun sôi (nhà tớ bán hàng nước mà...)
Kèm theo là dẫn chứng. (Access2000)

paulsteigel
13-04-2005, 19:46
Đã lâu lắm không thấy ai tham gia vào mục này... mình vui song cũng buồn. Dạo này bận quá nên chẳng có nhiều thời gian tìm kiếm cái gì hay hay cho vào thêm.
Hôm nay quay lại thấy vưỡn thế, kế cũng hơi buồn, nhưng chẳng sao.
Chủ đề hôm nay là:
Biến Excel thành một ứng dụng có vẻ hoàn chỉnh nhé (từ Menu bar đến các tác vụ đều thành của bạn). Các bạn sẽ thấy là mình thậm chí có thể làm được nhiều hơn thế để giải quyết các công việc thường nhật của mình...
Tôi sẽ không thể giới thiệu về cái định gửi theo đây, song tôi nghĩ các bạn có thể dùng được một số công cụ tôi đã gửi gắm trong chương trình này.
http://www.sfdp.net/Libs/gen/Exl/VdpExl.zip
Nay kính thư đã nhẩy!
Chẳng biết cái link này có làm việc không chứ!!!
Nếu không làm việc, các bạn gửi thông báo cho tôi theo: ngocdd@itprog.gov.vn hoặc vào thẳng cái trang ý http://www.sfdp.net nhé.

paulsteigel
16-04-2005, 17:00
.... Kể cũng lạ nhỉ, có vẻ như không đắt hàng rồi... hihi
Hôm nay tớ lại giới thiệu với các bạn một chút về cách tạo các hàm người dùng định nghĩa (UDF) trong Excel để phục vụ cho nhu cầu riêng của mình nhé.
Excel hỗ trợ việc xây dựng các hàm người dùng rất mạnh thông qua nhúng trực tiếp vào phần Module của bảng tính hoặc thông qua các Add-In.
Vấn đề tôi đặt ra hôm nay không mới song có thể một số trong các bạn chưa nắm qua nhỉ.
Bài toán là, tạo ra một hàm bổ sung cho bộ công thức của các bạn, theo đó mỗi khi bạn muốn chuyển đổi đoạn văn bản từ bảng mã này sang Unicode hoặc ngược lại thì chỉ cần chèn vào Cell công thức dạng: =Tounicode(A1,,true) là có kết quả ngay.
Cách làm như sau:
1. Tạo một bảng tính mới và lưu thành dạng Addin nhé (File, Save as và phần file type chọn Addin là xong)
2. Chọn Tools/ Macro/ Visual Basic Editor và màn hình soạn thảo của VBE hiện ra.
3. Thêm một Module mới vào VBProject của tập tin đang làm việc bằng cách nhấn phải chuột vào VBProject và chọn Add Module.
Sau đó bạn chỉ việc dán đoạn mã sau đây vào Code module là đã xong nửa quãng đường rồi.
Option Explicit

Function GetUTF8String(sKeyCode)
Dim UtfArr, UnicodeArr
Dim i
UtfArr = Array("á", "à ", "ả", "ã", "ạ", "ă", "ắ", "ằ", "ẳ", "ẵ", "ặ", "â", "ấ", "ầ", "ẩ", "ẫ", "ậ", "é", "è", "ẻ", "ẽ", "ẹ", "ê", "ế", "ề", "ể", "á»…", "ệ", "í", "ì", "ỉ", "Ä©", "ị", "ó", "ò", "ỏ", "õ", "ọ", "ô", "ố", "ồ", "ổ", "á»—", "á»™", "Æ¡", "á»›", "ờ", "ở", "ỡ", "ợ", "ú", "ù", "ủ", "Å©", "ụ", "Æ°", "ứ", "ừ", "á»­", "ữ", "á»±", "ý", "ỳ", "á»·", "ỹ", "ỵ", "Ä‘", "Á", "À", "Ả", "Ã", "Ạ", "Ä‚", "Ắ", "Ằ", "Ẳ", "Ẵ", "Ặ", "Â", "Ấ", "Ầ", "Ẩ", "Ẫ", "Ậ", "É", "È", "Ẻ", "Ẽ", "Ẹ", "Ê", "Ế", "Ề", "Ể", "Ễ", "Ệ", "Í", "ÃŒ", "Ỉ", "Ĩ", "Ị", "Ó", "Ã’", "Ỏ", "Õ", "Ọ", "Ô", "Ố", "á»’", "á»”", "á»–", "Ộ", "Æ ", "Ớ", "Ờ", "Ở", "á» ", "Ợ", "Ú", "Ù", "Ủ", "Ũ", "Ụ", "Ư", "Ứ", "Ừ", "Ử", "á»®", "á»°", "Ý", "Ỳ", "Ỷ", "Ỹ", "á»´", "Đ")
UnicodeArr = Array(225, 224, 7843, 227, 7841, 259, 7855, 7857, 7859, 7861, 7863, 226, 7845, 7847, 7849, 7851, 7853, 233, 232, 7867, 7869, 7865, 234, 7871, 7873, 7875, 7877, 7879, 237, 236, 7881, 297, 7883, 243, 242, 7887, 245, 7885, 244, 7889, 7891, 7893, 7895, 7897, 417, 7899, 7901, 7903, 7905, 7907, 250, 249, 7911, 361, 7909, 432, 7913, 7915, 7917, 7919, 7921, 253, 7923, 7927, 7929, 7925, 273, 193, 192, 7842, 195, 7840, 258, 7854, 7856, 7858, 7860, 7862, 194, 7844, 7846, 7848, 7850, 7852, 201, 200, 7866, 7868, 7864, 202, 7870, 7872, 7874, 7876, 7878, 205, 204, 7880, 296, 7882, 211, 210, 7886, 213, 7884, 212, 7888, 7890, 7892, 7894, 7896, 416, 7898, 7900, 7902, 7904, 7906, 218, 217, 7910, 360, 7908, 431, 7912, 7914, 7916, 7918, 7920, 221, 7922, 7926, 7928, 7924, 272)

For i = 0 To 133
If CLng(UnicodeArr(i)) = CLng(sKeyCode) Then
GetUTF8String = UtfArr(i)
Exit For
End If
Next
End Function

Function ToUnicode(txtString As String, Optional isReversed As Boolean = False, Optional toUTf8 As Boolean = False) As String
' This function will do the conversion of text string into unicode
Dim iStr As String, repTxt As String, mText As String
Dim i As Long, j As Long
Dim iUnicode As Variant ' array to keep unicode char set
Dim iTCVN As Variant ' array to keep TCVN char set
Dim iProcList() As String ' array to keep what to convert

'parse the parameter into this local variable
iStr = txtString
mText = txtString
Dim fLang
fLang = "V"
If fLang = "E" Then GoTo fExit
iUnicode = Array(225, 224, 7843, 227, 7841, 259, 7855, 7857, 7859, 7861, 7863, 226, _
7845, 7847, 7849, 7851, 7853, 233, 232, 7867, 7869, 7865, 234, 7871, 7873, 7875, _
7877, 7879, 237, 236, 7881, 297, 7883, 243, 242, 7887, 245, 7885, 244, 7889, 7891, _
7893, 7895, 7897, 417, 7899, 7901, 7903, 7905, 7907, 250, 249, 7911, 361, 7909, _
432, 7913, 7915, 7917, 7919, 7921, 253, 7923, 7927, 7929, 7925, 273, 193, 192, 195, _
258, 194, 212, 416, 431, 272)

iTCVN = Array(184, 181, 182, 183, 185, 168, 190, 187, 188, 189, 198, 169, 202, 199, 200, _
201, 203, 208, 204, 206, 207, 209, 170, 213, 210, 211, 212, 214, 221, 215, 216, 220, _
222, 227, 223, 225, 226, 228, 171, 232, 229, 230, 231, 233, 172, 237, 234, 235, 236, _
238, 243, 239, 241, 242, 244, 173, 248, 245, 246, 247, 249, 253, 250, 251, 252, 254, _
174, 193, 192, 195, 161, 162, 164, 165, 166, 167)

' Reenlarge the array
ReDim iProcList(1, 133)
' process the vowel only and covert to asc code
For i = 1 To Len(mText)
repTxt = Mid(mText, i, 1)
If AscW(repTxt) > 122 Then
iStr = Replace(iStr, repTxt, "[" & AscW(repTxt) & "]")
mText = Replace(mText, repTxt, " ")
' write the processed list
iProcList(1, j) = "[" & AscW(repTxt) & "]"
If toUTf8 Then
iProcList(0, j) = GetElementNo(AscW(repTxt), iUnicode)
Else
If isReversed Then
' this is to unicode
iProcList(0, j) = GetElementNo(AscW(repTxt), iUnicode)
Else
iProcList(0, j) = GetElementNo(AscW(repTxt), iTCVN)
End If
End If
j = j + 1
End If
Next
If j = 0 Then
ToUnicode = txtString
Exit Function
End If
ReDim Preserve iProcList(1, j - 1)
' now convert to unicode
For i = 0 To UBound(iProcList, 2)
If toUTf8 Then
iStr = Replace(iStr, iProcList(1, i), GetUTF8String(iUnicode(Val(iProcList(0, i)))))
Else
If isReversed Then
iStr = Replace(iStr, iProcList(1, i), ChrW(iTCVN(Val(iProcList(0, i)))))
Else
iStr = Replace(iStr, iProcList(1, i), ChrW(iUnicode(Val(iProcList(0, i)))))
End If
End If
Next
fExit:
ToUnicode = iStr
End Function

Private Function GetElementNo(iTxt As Long, iObj As Variant) As String
Dim i As Long
For i = 0 To UBound(iObj)
If iTxt = iObj(i) Then
GetElementNo = CStr(i)
Exit For
End If
Next
End Function

4. Bây giờ bạn lưu tập tin lại và bạn đã có thể sử dụng hàm ToUnicode() bình thường.
Lưu ý một chút nhé:
ToUnicode([Tham chiếu ô],[Chuyển về TCVN mặc định là False],[Chuyển về UTF-8 mặc định là False])
Thế là được rồi/ chuỗi text có thể là Unicode hoặc TCVN...
Tóm lại là bạn có thể sử dụng để viết nhiều công cụ khác theo ý của mình đúng không.
Một số vấn đề:
+ Nếu bạn đưa code vào Addin thì bạn có thể sử dụng công thức ở trên bất kỳ bảng tính nào - với điều kiện Addin này sau đó được chọn ở chế độ Cài đặt (Installed) - Tools -> Addin -> leave the Addin name checked.
+ Nếu bạn đưa code vào tài liệu làm việc hiện thời thì chỉ sử dụng được công thức đó ở tài liệu hiện thời mà thôi.
Thế đã nhỉ....

enemykill1
20-04-2005, 19:36
Mấy bài viết của bác rất có giá trị, nhưng hơi khó cho người không biết visual basic.
không sao ai mê thì tự khắc phải biét.

Hỏi nè,

Tôi design một cái trang excel nhưng tôi muốn rằng các khóa các cột các dòng, không cho người sử dụng di chuyển, nhưng được phép nhập liệu vào (cũng có thể không)

Làm như thế nào hả bác.

Thanks

paulsteigel
21-04-2005, 10:15
Tớ chưa hiểu rõ ý bạn lắm, “Dịch chuyển dòng, cột” ở đây có phải là thay đổi kích thước dòng, cột không nhỉ?
Excel có chức năng bảo vệ đối với các đối tượng Cells (các ô), Sheet (Bảng tính), Workbook (tập bảng tính) và tất cả các đối tượng thuộc về các lớp trên.
Do đó khi bạn muốn bảo vệ không cho người dùng thay đổi nội dung của bảng tính song lại cho phép họ thay đổi nội dung một số ô thì có thể làm như sau:
Vào phần code module của Bảng tính, chọn Thisworkbook (Nhấn kép chuột vào đó). Trong hộp chọn General, hãy chọn Workbook, trong phần Declarations chọn Open Tất nhiên Excel sẽ tự động tạo ra một thủ tục cho sự kiện Open có dạng:
Private Sub Workbook_Open()
‘ /...../
End Sub
Bạn hãy chèn một đoạn code sau vào thủ tục đó
Private Sub Workbook_Open()
‘ Thủ tục để khoá bảng tính và một số cells
LockSheetAndCells
End Sub
Chèn tiếp thủ tục sau vào Code modul của Thisworkbook
Private Sub LockSheetAndCells()
Sheet1.Unprotect ‘ Bỏ tất cả các bảo vệ trước đó
‘ Khoá một số ô của bảng tính
Sheet1.Cells(1, 1).Locked = False
Sheet1.Cells(6, 3).Locked = False
Sheet1.Cells(7, 4).Locked = False
‘ Thiết lập bảo vệ
Sheet1.Protect Password:="", Contents:=True
‘ Để xem cú pháp của lệnh Protect thì bạn có thể tham khảo phần trợ giúp của Excel
End Sub
‘ Như thế người dùng chỉ có thể thay đổi các cell nói trên của bảng tính. Nếu bạn còn muốn xác lập cơ chế kiểm tra nội dung của các giá trị, bạn có thể thêm một thủ tục vào codemodule của sheet 1 ví dụ:
Private Sub Worksheet_Change(ByVal Target As Range)
‘ chỉ cho người dùng nhập vào các giá trị là text chẳng hạn... ví dụ thôi (muốn làm cụ thể hơn thì phải chỉnh lại cái này
If Val(Target) <> 0 Then Target = ""
End Sub
Thế thôi nhỉ, có gì các bạn cứ hỏi thêm nhé

enemykill1
21-04-2005, 18:41
Hi bạn,

Hay lắm, nhưng có điều tôi design không để macro vô được, vì cái này được gắn vào web để cho người ta download.

Nên người sử dụng không rành khi hiện thông báo cảnh báo virus của macro. Họ liền Cancel. Do đó tôi tìm cái lệnh khóa, lúc trước tôi có làm qua rồi (nhưng bây giờ không nhớ lệnh đó nữa).

Dù sao cảm ơn bạn nhiều.

Tôi sẽ tự mò sau.

Thanks friend.

paulsteigel
21-04-2005, 20:06
Thế thì bạn làm bằng tay nhé, cái macro đó là tớ làm một cách tự động, còn thực tế thì bạn có thể làm đơn giản bằng cách chọn Tools/ Chọn Protect Allow user to edit range, sau đó bạn nhập vào range và nhấn Protect với mật khẩu là xong, cách này cũng giống như dùng Macro / bạn có thể đặt Macro đó vào trong bảng tính của bạn, hoặc một addin khác (sửa đổi đôi chút về tên bảng tính...) sau đó thực thi macro đó và bạn sẽ có được một tập tin excel như ý.
Chúc bạn thành công.

nhacsydom
22-04-2005, 09:08
Quả thật những bài viết của bạn rất hay, rất bổ ích cho những người làm văn phòng và lập trình VBA. Trước tiên xin cám ơn bạn rất nhiều về loạt bài viết trên.
Hôm nay mình xin hỏi bạn có biết cách nào dùng VBA trong access để khóa không cho người dùng import các table trong access không?. Ví dụ như mình có 1 database dulieu.MDB gồm nhiều bảng dữ liệu quan trọng. Mình đã khóa không cho mở trực tiếp database này rồi. Nhưng có những kẻ dùng phương thức import database để import các bảng dữ liệu của mình hoặc link table để xem hoặc sửa đổi dữ liệu (nếu bạn dùng set password của MS access thì trên thị trường có phần mềm bẻ khóa rất dễ dàng để tìm ra password.)
Bạn có thể giúp mình được không?
Cám ơn trước nha.

paulsteigel
22-04-2005, 15:16
Vâng đây quả thật là một chủ đề khó! Nhiều người đã tìm cách, nhiều nhà sản xuất cũng đã tìm cách để khoá không cho truy cập bất hợp pháp vào các bảng dữ liệu.
Microsoft đưa ra các công cụ để có thể bảo vệ các tập tin mdb khỏi sự truy cập bất hợp pháp, tuy vậy đến nay các công cụ này vẫn tỏ ra là một thứ để trang trí nhiều hơn là để bảo vệ tập tin.
+ Cách 1, bảo vệ bằng mật khẩu cấp CSDL: Cách này hoàn toàn có thể bị vô hiệu bằng các công cụ bẻ khoá mật khẩu ( không hiểu sao Microsoft vẫn dùng công nghệ mã hoá XOR đơn giản cho cơ sở dữ liệu mdb).
+ Cách 2, bảo vệ bằng cấp quyền người dùng: Cách này tạo ra các lớp người dùng với quyền khác nhau cùng với công cụ mã hoá có sẵn, tuy vậy công cụ này có vẻ như tạo ra nhiều phiền toái cho người sử dụng hơn là để bảo vệ họ. Thông tin vẫn bị mất bằng một vài thao tác khá đơn giản.
Tôi không có nhiều kinh nghiệm trong bảo mật cơ sở dữ liệu song từ kinh nghiệm, tôi thấy các cách sau đây có vẻ khả thi và an toàn nhất, song lại ảnh hưởng đến tốc độ ứng dụng:
Cách 1: Áp dụng công cụ mã hoá các đơn vị dữ liệu phổ biến hiện có ngay trong quá trình khai thác dữ liệu với một chìa khoá giải mã độc lập nằm ngoài cơ sở dữ liệu: Cách này dùng phổ biến hiện nay để bảo vệ các thông tin quy mô nhỏ song nhạy cảm như: Mật khẩu, tên người dùng ...
Thuật toán mã hoá phổ biến là MD5, RC4 ....
Với các thông tin quy mô lớn thì việc này làm chậm ứng dụng rất nhiều.
Cách 2: Áp dụng công cụ mã hoá tiền thực thi: Chạy một ứng dụng giải mã cơ sở dữ liệu trước khi khai thác dữ liệu sau đó làm việc trên tập tin đã giải mã. Khi kết thúc sử dụng ứng dụng, việc mã hoá lại được thực hiện đối với cơ sở dữ liệu, tập tin tạm thời sẽ bị xoá bỏ. Cố gắng truy cập hoặc bẻ khoá đối với cơ sở dữ liệu chỉ làm hỏng csdl hoặc không thành công (Tỷ lệ thành công là rất thấp... và tuỳ thuộc vào độ dài của chìa khoá giải mã mà bạn đặt)
Thuật toán thông dụng nhất hiện nay là Huffman do đặc tính có độ an toàn cao kèm theo chức năng nén dữ liệu.
Túm lại, như cách tôi vẫn làm thì tôi viết 1 ứng dụng bằng VB để thực hiện các công việc mã hoá, nén CSDL trước khi sử dụng, mã khoá độc lập được giấu trong Registry hoặc trong một văn bản nào đó. Cách này thường có độ an toàn cao hơn các biện pháp khác song vẫn không làm ảnh hưởng lớn đến tốc độ ứng dụng. Tuy vậy, cũng chỉ bảo vệ an toàn cho cơ sở dữ liệu trước những tay mới thôi, còn với chuyên gia bẻ khoá thì hiện giờ thế giới vẫn bó tay....
Nay kính thư

enemykill1
22-04-2005, 18:57
Tìm phần mềm hide window XP,

Thế là xong, khóa lần đầu khi mở Database.
Lần thứ hai là password của Database.

Thật ra các phần mềm dò tìm password tôi thấy không hiệu quả cho lắm nếu bạn kết hợp ký tự ( ví dụ: h245#j1123).

Chúc bạn thành công.


Thế thì bạn làm bằng tay nhé, cái macro đó là tớ làm một cách tự động, còn thực tế thì bạn có thể làm đơn giản bằng cách chọn Tools/ Chọn Protect Allow user to edit range, sau đó bạn nhập vào range và nhấn Protect với mật khẩu là xong, cách này cũng giống như dùng Macro / bạn có thể đặt Macro đó vào trong bảng tính của bạn, hoặc một addin khác (sửa đổi đôi chút về tên bảng tính...) sau đó thực thi macro đó và bạn sẽ có được một tập tin excel như ý.
Chúc bạn thành công.,

thanks a lot.

Bon travail

nhacsydom
23-04-2005, 08:33
Như vậy có thể khẳng định là không thể dùng VBA để khoá chức năng Import và link table của MS Access. Có đúng vậy không ? Bạn cho mình biết ý kiến đi.
Chào

paulsteigel
23-04-2005, 09:59
"Vâng đúng vậy, không có cách nào khoá được import, link bằng VBA một cách triệt để". Ở đây có sự nhầm lẫn về khái niệm một chút bạn ạ:
MDB được thiết kế với ý tưởng ban đầu là cơ sở dữ liệu, việc tích hợp thêm VBA vào MDB được bổ sung thêm.
Với một cơ sở dữ liệu MDB, các đối tượng bảng là đơn vị có thể truy cập được từ các ứng dụng khác để khai thác dữ liệu, các đối tượng Form, module macro là các đối tượng chỉ có thể khai thác và thực thi được với MSaccess, do đó nói dùng VBA để khoá CSDL là sai. Việc khoá Csdl chỉ thực hiện được thông qua việc ngăn cản truy cập đối với đối tượng bảng - công việc này diễn ra ở lớp ngoài. VBA của Mdb nằm ở lớp trong, các thực thi này chỉ thực hiện được khi có Ms access. Nên việc dùng một cơ cấu nằm trong để bảo vệ lớp ngoài là không được.
Thêm vào đó, chức năng link, import là chức năng của cấp ứng dụng và đều sử dụng trên nền của Data engine (DAO, RDO...) do vậy nếu bạn chống lại việc import, link thì phải can thiệp vào data engine để loại bỏ khả năng kết nối, điều này lại không khả thi do các nguyên nhân sau:
+ Bạn đã ngăn cản chính bạn trong việc khai thác dữ liệu.
+ Bạn khó có thể can thiệp vào Dataengine do không biết mã nguồn.
+ Nếu bạn làm được thì bạn chỉ bảo vệ được ở máy tính củabạn thôi vì DAO, RDO... là chuẩn kết nối dữ liệu chung, giống nhau ở tất cả các ứng dụng khai thác dữ liệu
Vậy thì, muốn chống lại việc import hay link một cách thành công (lúc này được gọi là chống khai thác dữ liệu trái phép, vì bản thân người dùng đã lấy được dữ liệu của bạn song họ có thể không đọc được nội dung thông tin) bạn chỉ có cách là mã hoá dữ liệu trong bảng hoặc mã hoá tiền khả thi như tôi đã trình bày.
....Nay kính thư....

Hoangthuthinh
23-04-2005, 10:06
http://www.echip.com.vn/echiproot/weblh/ctv/2001/npthao/ttoff8/

paulsteigel
23-04-2005, 10:10
1. Trả lời bạn Enemykill


Thật ra các phần mềm dò tìm password tôi thấy không hiệu quả cho lắm nếu bạn kết hợp ký tự ( ví dụ: h245#j1123).

Bạn Enemykill có thể đã nhầm lẫn, đến tận phiên bản 2003 thì chức năng khoá cơ sở dữ liệu bằng mật khẩu lớp ngoài vẫn sử dụng công nghệ XOR phân lớp. Cách này chẳng khó khăn gì cho các phần mềm bẻ khoá, họ chỉ cần dò phần Header, làm một vài cách so sánh thế là đã có thể bẻ khoá ngon lành.
Lý do mà MS vẫn dùng kiểu khoá dữ liệu này là vì: Các database engine vẫn truy cập vào MsAccess theo kiểu truyền thống và chưa có cải thiện trong việc giải mã một cơ sở dữ liệu phi môi trường đã được mã hoá. Phi môi trường có nghĩa là không có một ứng dụng hoàn thiện để cung cấp các chuẩn liên kết dữ liệu dạng hỏi đáp. SQL, MYSQL, ORACLE là các dataengine nền môi trường, muốn liên kết với dữ liệu của nó bạn phải vượt qua lớp ứng dụng quản lý dữ liệu trước. Trong khi Mdb, dbf, dbase... là chuẩn liên kết không phải qua lớp ứng dụng, do đó việc khoá hay không khoá dữ liệu đều phụ thuộc vào dataengine..... và thường thì các dataengine này đều cần tốc độ hơn là bảo mật do đó họ không thể mã hoá toàn bộ csdl mà chỉ mã hoá phần header của Mdb để ánh xạ lại vị trí bảng, kích thước bản ghi mà thôi. Nếu có đúng chìa khoá thì đọc đúng các nội dung trên, nếu không có chìa khoá hoặc chìa khoá sai thì không đọc được định dạng bảng và kích thước bản ghi..
....Nay kính thư....

nhacsydom
26-04-2005, 07:27
Cám ơn bạn Paulsteigel nhiều. Mình đã hiểu rõ vấn đề rồi.Tuy nhiên mình vẫn nghĩ là có thể dùng VBA để khóa chức năng import của MS access bằng cách loại bỏ hoặc ẩn menu import, cho dù chỉ trên một máy mà thôi (nếu copy .MDB sang máy khác vẫn bình thường). Ý nghĩ đó có khả thi không bạn?
Chào

paulsteigel
26-04-2005, 09:48
Vâng, cách của bạn rất hay, tuy nhiên cũng không khả thi lắm vì các lý do sau:
+ Chúng ta chỉ ẩn chức năng này thôi do đó nó vẫn tồn tại và vẫn có thể truy cập vào nó theo cách này hoặc cách khác.
+ Tay chơi nào biết một chút về câu lệnh của Access thì họ hoàn toàn có thể sử dụng lệnh của macro hoặc vài đoạn code để thực thi sự kiện nhập dữ liệu của bạn.
Tiện đây tôi quay trở lại với cách làm ẩn menu của bạn, để làm được thì bạn cần phải biết chỉ số (ID) của lệnh này trong hệ thống vài ngàn lệnh của Access, nếu tôi không lầm thì cũng đã làm một bài viết về cách lấy toàn bộ ID của Menu Excel rồi thì phải, với Access cũng tương tự thôi.
Sau khi lấy được các ID này, bạn chỉ cần làm cho nó disable là được.
Hôm nay bận quá, nên tôi sẽ trả lời sâu thêm về vấn đề này vào dịp khác hoặc bạn Email cho tôi nhé.

tdthang
27-04-2005, 11:10
Chào bạn Paulsteigel, trước giờ khi cần bảo vệ dữ liệu trong Access tui vẫn thường sử dụng user-level security, hôm nay nghe bạn nói "Thông tin vẫn bị mất bằng một vài thao tác khá đơn giản" thì tui khá kinh hãi. Bạn có thể hướng dẫn cho tui các thao tác đơn giản đó để tui test thử mấy file Access của tui được không ? Cám ơn bạn trước.

namlh
28-04-2005, 08:55
Chao ban,

Minh dang dung 01 Form trong Excel User nhap du lieu va sau do luu du lieuvao bang Access.

Trong Form co nhieu textbox trong do co 01 textbox dung de nhap ngay, textbox nay cung co the blank. Khi User nhap du lieu vao textbox nay tren Form thi minh co the luu vao Access duoc. Nhung neu textbox nay blank, nghia la User khong nhap du lieu vao thi khi luu vao Access bao loi 'Type mismatch'.

Theo suy doan cua minh thi vi field trong Access luu textbox nay co data type la Date/Time nen no khong chap nhan du lieu la blank. Field nay chi chap nhan 01 gia tri ngay nao do hoac null.

Co ban nao giup minh lam sao de luu blank vao field nay hoac chuyen du lieu blank tu Form thanh null truoc khi luu vao Access.

Cam on ban rat nhieu.

Nam

paulsteigel
28-04-2005, 11:21
<<Chào bạn Paulsteigel, trước giờ khi cần bảo vệ dữ liệu trong Access tui vẫn thường sử dụng user-level security, hôm nay nghe bạn nói "Thông tin vẫn bị mất bằng một vài thao tác khá đơn giản" thì tui khá kinh hãi. Bạn có thể hướng dẫn cho tui các thao tác đơn giản đó để tui test thử mấy file Access của tui được không ? Cám ơn bạn trước. >>.
Có lẽ tôi không dám mạn đàm về Mdb Security nữa, mời bạn vào forum này đọc đoạn này có lẽ rõ hơn nhỉ: http://www.experts-exchange.com/Databases/MS_Access/Q_21141537.html
Thêm một cái này nữa:
http://www.eggheadcafe.com/ng/microsoft.public.access.security/default.asp
http://support.microsoft.com/default.aspx?scid=%2Fsupport%2Faccess%2Fcontent%2F secfaq.asp
Nếu có gì bạn cứ nói nhé, đây là chủ đề nhiều người đau đầu đấy ạ. À quên, bạn cứ copy cái tập tin mdb của bạn sang máy khác, tìm file system.mdw và đổi tên thành system.aaa thôi, và thử xem... hihi


Chao ban,

Minh dang dung 01 Form trong Excel User nhap du lieu va sau do luu du lieuvao bang Access.

Trong Form co nhieu textbox trong do co 01 textbox dung de nhap ngay, textbox nay cung co the blank. Khi User nhap du lieu vao textbox nay tren Form thi minh co the luu vao Access duoc. Nhung neu textbox nay blank, nghia la User khong nhap du lieu vao thi khi luu vao Access bao loi 'Type mismatch'.

Theo suy doan cua minh thi vi field trong Access luu textbox nay co data type la Date/Time nen no khong chap nhan du lieu la blank. Field nay chi chap nhan 01 gia tri ngay nao do hoac null.

Co ban nao giup minh lam sao de luu blank vao field nay hoac chuyen du lieu blank tu Form thanh null truoc khi luu vao Access.

Cam on ban rat nhieu.

Nam
Chúng ta cần phân biệt nhé: Blank = trắng (Ngầm hiểu cho kiểu ký tự), empty=rỗng (Dùng để kiểm tra xem một biến đối tượng là rộng hay không), null (Ngầm hiểu là giá trị rỗng cho mọi đối tượng và kiểu dữ liệu)
Vì thế bạn cần đặt một lệnh kiểm tra xem texbox là trắng hay không bằng cách sử dụng dẫu nháy kép rỗng, nếu trắng thật thì gán giá trị Null, đảm bảo được.
Private Sub CommandButton1_Click()
Dim db As Database
Dim rs As Recordset
Set db = OpenDatabase("C:\My Documents\db1.mdb")
Set rs = db.OpenRecordset("Select * from Activity;")
With rs
.AddNew
.Fields(1) = "A"
.Fields(2) = "B"
if TextBox1.text="" then .Fields("Day") = Null else .Fields("Day") = format(TextBox1.text,"dd/mm/yyyy")
.Update
.Close
End With
End Sub

tdthang
28-04-2005, 14:52
Tui thử đổi tên file system.mdw thành system.aaa thì thấy không mở được file mdb đã bật user-level security, đồng thời 1 file system.mdw mới được tạo ra.
Tiếc là tui không up file test.mdb lên ddth.com được (forbidden). Không biết còn cách nào để gửi được cho bạn để nghiên cứu thử.

Link trên Expert Exchange không vào xem được (phải có membership)
Link thứ 2 thì nhiều topic quá.
Link trên microsoft thì lúc trước cũng đọc qua rồi.

paulsteigel
28-04-2005, 17:23
Thế thì bạn gửi cho tớ nhé: ngocdd@itprog.gov.vn
Nick yahoo của tớ là dangdinhngoc, Okay! tớ lại phải quay lại vấn đề này vậy, mặc dù mdb security đã được bàn luận khá nhiều.... nhưng tớ sẽ không muốn đi lạc đề khỏi chủ đề Office VBA đâu!!!
Tks bạn nhiều nhé.
Tiện đây tôi bổ sung thêm 1 thuật toán mã hoá cũng khá tiện dụng là RC4 mặc dù hiện nay người ta đã ít dùng nó hơn:
* Chìa khoá mã hoá: AJHGJHSJAH6433ASJHASAL981467
Bạn hãy cất chìa khoá này đâu đó trong máy tính hoặc registry để tránh bị đánh cắp
* Thuật toán xử lý:
Cách gọi hàm mã hoá:***=RC4([chuỗi cần mã hoá],[chìa khoá]
Function RC4(ByRef pStrMessage, ByRef pStrKey)
Dim lBytAsciiAry(255)
Dim lBytKeyAry(255)
Dim lLngIndex
Dim lBytJump
Dim lBytTemp
Dim lBytY
Dim lLngT
Dim lLngX
Dim lLngKeyLength

' Validate data
If Len(pStrKey) = 0 Then Exit Function
If Len(pStrMessage) = 0 Then Exit Function

' transfer repeated key to array
lLngKeyLength = Len(pStrKey)
For lLngIndex = 0 To 255
lBytKeyAry(lLngIndex) = Asc(Mid(pStrKey, ((lLngIndex) Mod (lLngKeyLength)) + 1, 1))
Next

' Initialize S
For lLngIndex = 0 To 255
lBytAsciiAry(lLngIndex) = lLngIndex
Next

' Switch values of S arround based off of index and Key value
lBytJump = 0
For lLngIndex = 0 To 255

' Figure index to switch
lBytJump = (lBytJump + lBytAsciiAry(lLngIndex) + lBytKeyAry(lLngIndex)) Mod 256

' Do the switch
lBytTemp = lBytAsciiAry(lLngIndex)
lBytAsciiAry(lLngIndex) = lBytAsciiAry(lBytJump)
lBytAsciiAry(lBytJump) = lBytTemp

Next
lLngIndex = 0
lBytJump = 0
For lLngX = 1 To Len(pStrMessage)
lLngIndex = (lLngIndex + 1) Mod 256 ' wrap index
lBytJump = (lBytJump + lBytAsciiAry(lLngIndex)) Mod 256 ' wrap J+S()

' Add/Wrap those two
lLngT = (lBytAsciiAry(lLngIndex) + lBytAsciiAry(lBytJump)) Mod 256

' Switcheroo
lBytTemp = lBytAsciiAry(lLngIndex)
lBytAsciiAry(lLngIndex) = lBytAsciiAry(lBytJump)
lBytAsciiAry(lBytJump) = lBytTemp

lBytY = lBytAsciiAry(lLngT)

' Character Encryption ...
RC4 = RC4 & Chr(Asc(Mid(pStrMessage, lLngX, 1)) Xor lBytY)
Next

End Function

paulsteigel
15-05-2005, 09:29
Lâu quá hôm nay mới ghé qua được....
Hôm nay tớ kính biếu các bác một cách giúp Office hiển thị được các thông điẹm (Message) tiếng việt bằng Unicode dựng sẵn!.
Chúng ta thiết kế một form giống như form hiển thị bằng lệnh msgbox của VB sau đó đặt các nút bấm, hình ảnh cần thiết vào để xử lý.
Viết một hàm với tến là Msgbox() để override hàm msgbox của VB sau đó chúng ta sẽ có một msgbox mới có thể hiển thị các thông điệp tiếng việt Unicode rất tốt, hihi....
Ai muốn có mã nguồn thì gửi cho tớ nhé! ngocdd@itprog.gov.vn
Nay kính thư...

namlh
19-05-2005, 14:13
Chao ban,

Minh tao listbox trong Excel va viet 01 macro trong Excel de lay du lieu tu Access, nhung trong du lieu co mot so field la null nen se phat sinh loi:

Sub LisboxLoad()

Dim objMyConn, objMyRecordset, strSQL
Dim x, y, i, j As Single
Dim MyArray() As String
LstCustName.ColumnCount = 5
LstCustName.ColumnWidths = "2 in;0.5 in;0.5 in;0.5 in;0.5 in"
Set objMyConn = CreateObject("ADODB.Connection")
Set objMyRecordset = CreateObject("ADODB.Recordset")

objMyConn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Data Source=F:\Nam\Macro\Excel.mdb;"
objMyConn.Open
strSQL = "select * from CustomerInfo"
Set objMyRecordset.ActiveConnection = objMyConn
objMyRecordset.Open Source:=strSQL, CursorType:=adOpenKeyset, _
LockType:=adLockOptimistic, Options:=adCmdText
x = objMyRecordset.RecordCount
y = objMyRecordset.Fields.Count - 1
ReDim MyArray(x, y)
i = 0

While Not objMyRecordset.EOF
For j = 0 To y

If IsNull(objMyRecordset.Field(j)) Then
MyArray(i, j) = ""

Else
MyArray(i, j) = objMyRecordset.Fields(j)
End If

Minh dung ham isnull de kiem tra xem neu field null thi gan cho mang la "" nhung phat sinh loi khi dung ham isnull.

Ban vui long giup minh lam sao de tranh loi nay hoac co cach nao de lay du lieu nhieu cot vao Listbox trong truong hop co mot so filed null. Chang han:

1 2 3

Nam Le Hai
An
Phuong My

Cam on ban rat nhieu.

Nam

paulsteigel
19-05-2005, 18:39
Bạn Namlh à: Thế này nhé, bạn dùng hàm isnull không sai song nếu theo những gì bạn đăng ở đây thì bạn bị sai một số chỗ như thế này:
If IsNull(objMyRecordset.Field(j)) Then
Thuộc tính field không phải là như vậy mà là fields.
Bạn chỉ cần sửa thành fields là xong.
Tiện đây tôi cũng góp ý thêm với bạn một số chỗ:
Bạn nên khai báo kiểu dữ liệu cho các biến một cách hoàn chỉnh:
VB sẽ không coi i,j,k,l as single là một kiểu khai báo chuẩn mà nếu đã định khai báo thì phải làm thế này: i as single, j as single ....
Theo nữa do việc bạn không khai báo kiểu của objMyRecordset nên bạn đã không khai thác được chức năng tự hiển thị thuộc tính của IDE do đó đã gặp lỗi trên đây.
Tiếp nữa. Bạn đã xác định là listbox có 5 cột, vậy bạn cũng nên giới hạn cái Array ở 5 cột, vì nếu y ở đây không phải là 4 mà là hơn thế nữa thì có thể bạn sẽ phải khổ vì dữ liệu sẽ không hiện đúng như mình muốn...
Túm lại tôi chép ra một đoạn mã nguồn để bạn tiện tham khảo nhé:
Dim objMyConn As Connection, objMyRecordset As Recordset, strSQL As String
Dim x As Single, y As Single, i As Single, j As Single
Dim MyArray() As String
' nên sửa chỗ này, thay vì dùng scripting object, ta nên dùng tham chiếu thì tiện nhất. Hoặc nếu bạn muốn tránh việc sai thuộc tính thì nên đặt tham chiếu trước và khai báo như tôi đã làm sau đó bỏ tham chiếu và chuyển khai báo thành kiểu object .... hehe phức tạp quá đúng không? Nhưng cách này sẽ làm giảm khả năng gặp lỗi...
Set objMyConn = CreateObject("ADODB.Connection")
Set objMyRecordset = CreateObject("ADODB.Recordset")

objMyConn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Data Source=F:\Nam\Macro\Excel.mdb;"
objMyConn.Open
strSQL = "select * from CustomerInfo;"
Set objMyRecordset.ActiveConnection = objMyConn
objMyRecordset.Open Source:=strSQL, CursorType:=adOpenKeyset, _
LockType:=adLockOptimistic, Options:=adCmdText

' Get value for x and y properly
x = objMyRecordset.RecordCount
y = objMyRecordset.Fields.Count

' if you are not so sure howmany column shall be, Okay do this
LstCustName.ColumnCount = y + 1

' Okay for better viewing your list, check for columns and assign colum width properly
LstCustName.ColumnWidths = "2 in;0.5 in;0.5 in;0.5 in;0.5 in"

ReDim MyArray(x, y)
'i = 0 you dont need this as i will be automatically assiged with value of 0

While Not objMyRecordset.EOF
For j = 0 To y
If IsNull(objMyRecordset.Fields(j + 2)) Then
MyArray(i, j) = ""
Else
MyArray(i, j) = objMyRecordset.Fields(j + 2)
End If
Next
i = i + 1
objMyRecordset.MoveNext
Wend
LstCustName.List = MyArray
' better clean up the connection setting here
objMyRecordset.Close
objMyConn.Close
Nay kính thư...

paulsteigel
21-05-2005, 14:08
Kiểu này thì tớ phải đổi tên chủ đề thành mỗi tuần một ví dụ thôi! Công việc cũng nhiều nên bây giờ vào ddth mỗi ngày và viết bài cho nó thấy sao mà khó thế ... nhưng thôi dù sao tớ cũng cố gắng vậy.
Mình thật sự mong mỏi có thể viết một cách hoàn chỉnh về bộ tài liệu hướng dẫn VBA cho tất cả những ai muốn bắt đầu một việc gì đó với VBA từ bước đơn giản nhất cho đến bước phức tạp hơn một chút.
Theo yêu cầu của một số bạn mới bắt đầu với VBA, tôi sẽ quay lại từ đầu và cùng các bạn bước những bước đầu tiên để có thể viết cho mình được một ứng dụng đơn giản với VBA. Trong quá trình viết, có gì sai, rất mong các cao thủ đóng góp và cho ý kiến nhé. Tôi luôn hy vọng sẽ có ai đó cùng tham gia để giúp cho ý tưởng này ngày càng hoàn thiện.
Các bác cho ý kiến đóng góp nhé....

paulsteigel
26-05-2005, 09:22
Không thấy ai góp ý nhỉ…
Thôi thế cũng được tôi sẽ cứ bắt đầu. 10 bài viết đầu của tôi sẽ tập trung vào các vấn đề sau:
1. Sơ lược về Office VBA – 2 bài
2. Đặc tính cơ bản của VBA trong các ứng dụng Office – 2 bài
3. Kiến thức đầu tiên về Macro 3 bài
4. Thử làm một Macro đầu tiên với Excel – 2 bài
5. Giải thuật và một số kinh nghiệm về thuật toán – 1 bài. phần này tổng kết các kinh nghiệm lập trình trước các bài toán đơn giản - rất mong mọi người tham gia phần này đông vui nhé.
Sau khi hoàn thành 10 bài viết này, nếu có thêm yêu cầu, ta sẽ vẫn tiếp tục với phần 6 là Macro trong word, Power point … khoảng 3 bài nữa (chẳng hiểu sao mình lại thích số 13)
Kết thúc phần I tôi sẽ chuyển sang phần 2, các kỹ năng cho người mới bắt đầu với Access
Phần này dự định sẽ bao gồm các mục sau
1. Access dưới góc nhìn là một ứng dụng ( chủ yếu nói đến khả năng lập trình trong Access) – sơ lược thôi – cái này giúp các bạn xem Access có thể giúp bạn làm gì.
(Tôi vẫn chưa hình dung rõ là nên đặt đề mục này thế nào, các cao thủ xem và điều chỉnh giúp nhé.)
2. Cấu trúc dữ liệu - phần này tôi rất mong có đóng góp của các cao thủ về Data Schema và cấu trúc dữ liệu.
3. Làm việc với Form, báo cáo và Query trong acces – bao gồm một số ví dụ và hướng dẫn đơn giản. Ngoài ra cũng kèm theo một số thủ thuật.
4. Các kỹ thuật với thực đơn trong ứng dụng nhiều module – Một số ví dụ và các kỹ thuật đơn giản để quản lý thực đơn.
5. Đối tượng ActiveX và COM trong Access. – chưa xác định
6. Đóng gói và bảo mật. – chưa xác định
Trên đây là đề xuất ban đầu đối với loạt bài viết về Office VBA. Kính mong các bạn tham gia và cho ý kiến đóng góp nhé. Nếu có ý kiến trực tiếp, các bạn cứ thư vào ngocddang@gmail.com nhé.
Nay kính thư.

Solana
27-05-2005, 08:50
Toi co 1 so kho khan khi lam viec tren Excel va da post len dien dan nho tu van giup nhung khong thay ai tra loi. Hy vong post o day se duoc ban paulsteigel chieu co doc va tra loi giup

Toi co 2 sheet trong 1 file Excel. Sheet1 la danh sach doi tuong (vi dung nhu: hoten, ngaysinh, ...). Toi muon Sheet2 loc du lieu tu Sheet1 (vi du cac doi tuong sinh nam 1990), khi thay doi o Sheet1 thi Sheet2 cung tu dong cap nhat. Xin cac ban huong dan giup cach thuc hien

Xin cam on nhieu.

paulsteigel
27-05-2005, 13:02
Thực sự là tôi chưa hiểu ý bạn lắm song tôi cũng thử nói lại xem mình hiểu có đúng không nhé?
+ Bạn có một sheet lưu trữ các thông tin về họ tên, ngày sinh.
+ Sheet2 có các thông tin lấy từ sheet1
+ Bạn thay đổi một số dữ liệu ở sheet1 và sheet2 phải thay đổi theo.
Điều khó hiểu ở đây là: sheet2 lọc dữ liệu gì từ sheet1? Cơ cấu lọc thế nào.
Còn nếu chỉ để giải quyết những vấn đề tôi gạch đầu dòng thì chỉ cần hàm Vlookup cũng đã quá được rồi.
Bạn nói rõ hơn nhé, hoặc mail cho tôi: ngocdd@itprog.gov.vn
Nay kính thư

Solana
27-05-2005, 15:54
Cam on ban da tra loi.

Toi xin giai thich ro hon: Sheet2 co cac truong (cot) giong nhu Sheet1 nhung cac dong (row) chi khop voi nhung gia tri loc thoi. Vi du toi muon Sheet2 hien thi cac doi tuong sinh nam 1990 chang han. No tuong tu cau lenh SQL:

SELECT * FROM Sheet1 WHERE YEAR([ngaysinh])=1990

Dieu quan trong o day la ket qua tra ve nam o Sheet2

Toi da thu cac ham VLOOKUP, HLOOKUP deu khong duoc vi gia tri tra ve cua cac ham nay la value (hoac array of value), khong phai la cac records (hay rows)

Toi nghi day la van de rat nhieu nguoi quan tam. Rat mong duoc ban huong dan

paulsteigel
27-05-2005, 17:03
Vâng tôi xin trả lời thế này
+ Excel là công cụ hỗ trợ tính toán bảng tính mạnh song nó lại không phải là công cụ tốt để trích lọc dữ liệu dạng các truy vấn SQL. Bản thân Excel cần khá nhiều tài nguyên để phục vụ cho quá trình theo dõi tính toán và các công thức. Do vậy yêu cầu của bạn là, với mỗi thay đổi bạn thực hiện tại sheet1, ngay lập tức cần phản ánh tại sheet2 là có thể được nhưng không hiệu quả do quá trình trích lọc dữ liệu sẽ làm Excel bận bịu và làm chậm hệ thống. Để giải quyết hiện tượng này. Bạn nên thiết kế một macro, để mỗi khi bạn kết thúc điều chỉnh tại sheet1, hãy thực thi macro này bằng tay để Excel rảnh tay lọc dữ liệu và chuyển qua ghi đè lên sheet2.
Với ít dữ liệu (dưới 300 dòng) thì có vẻ ổn nhưng nếu nhiều hơn thì cũng mệt đấy, gõ xong bạn sẽ phải chờ 1 đến 2 giây đề dữ liệu update tại Sheet2. Do đó tôi khuyến nghị nên dùng cách update sau khi hoàn tất điều chỉnh tại sheet1.
+ Nếu bạn muốn tránh ghi đè dữ liệu thì bảng tính sheet1 của bạn cần có một đặc điểm nào đó để nhận dạng các dòng (giống như trường khoá trong bảng dữ liệu). Khi macro thực hiện nó sẽ tìm các dòng đó tại Sheet1 và điều chỉnh dữ liệu của dòng với đặc điểm đó tại sheet2.
Về Macro, tôi giới thiệu với bạn cách sau –Giả định rằng sheet2 chứa giá trị kết xuất của lọc tất cả các đối tượng có năm sinh là ***x từ sheet1.
Cách1: Bạn hãy dùng chức năng advance filter
Cách này nhanh song đôi khi không kiểm soát được kết quả.
Cách 2: lọc tuần tự
+ Kiểm tra tất cả các dòng, đến dòng nào có dữ liệu trùng với dữ liệu cần lọc thì tạm dừng
+ Tìm dòng có khoá giống với dòng vừa tìm thấy tại sheet1, nếu không thấy thì dừng ở dòng cuối cùng và copy cả dòng đó ở sheet1 sang sheet2. Nếu tìm thấy thì chỉ ghi đè các thông tin ở dòng này tại sheet1 sang.
Vậy bạn cần 2 thuật toán:
a. Thuật toán tìm dòng có dữ liệu giống dữ liệu cần lọc và trả về số dòng
b. Thuật toán copy dữ liệu.
Tôi gợi ý đến thế. Nếu bạn cần phải viết cụ thể thuật toán thì mail cho tôi nhé.
Nay kính thư

Solana
28-05-2005, 09:36
Nếu dùng macro thì tôi sợ sẽ gây khó khăn cho người sử dụng. Nhiều chương trình diệt virus sẽ phá hỏng các file EXCEL chứa macro. Hơn nữa file dữ liệu nguồn của tôi khá lớn (4000-5000 dòng). Tôi thấy trong Excel có hỗ trợ cái gọi là Pivot Table không biết có dùng được với mục đích lọc dữ liệu của tôi không?

Tôi muốn học thêm 1 chút về Excel, bạn có thể giới thiệu giúp 1 số e-book hay sách (dạng advanced) về Excel được không?

paulsteigel
28-05-2005, 11:13
Thực ra theo cách tôi vẫn làm (khi chưa sử dụng Macro) trong các bài toán của bạn là dùng công thức If của Excel, tuy nhiên cũng hơi bất tiện một chút vì bạn không thể làm tự động được. Tôi giới thiệu một công thức thế này nhé
=IF(YEAR(Sheet1!$B2)=Sheet3!$A$2,Sheet1!D2,"")
Trong đó Sheet3!$A$2 là ô điều kiện. Sheet1 là dữ liệu gốc, công thức này đặt tại Sheet2,
Bạn copy toàn bộ công thức này vào sheet2 thì nó sẽ tự động lấy giá trị thoả mãn điều kiện.
Tuy nhiên sẽ có nhiều dòng trắng, để lọc được d liệu chuẩn, bạn nên dùng thêm công cụ autofilter sau này nhé.

Hôm nay tôi hướng dẫn các bạn một cách đơn giản để làm "MailMerge" trong Excel - đôi khi cũng khá tiện lợi cho các bạn không muốn phải dùng đến Word.
Yêu cầu:
+ Bạn có một bảng Excel chứa dữ liệu chuẩn để in ra, có tên là data.xls nằm cùng thư mục với thư mục chứa mẫu chuẩn, sheet chứa dữ liệu hãy đặt tên là data.
+ Một nhãn mẫu chuẩn đã thiết kế sẵn chứa các ô để điền dữ liệu. Chọn phần mẫu chuẩn và đặt tên cho nó là Sample.
Cách làm như sau:
a. Đầu tiên, hãy copy đoạn mã mẫu này vào một module của bảng tính Excel có chứa mẫu chuẩn.
(Nhấn Alt+F11 và vào môi trường soạn thảo VBA của Excel, thêm một module)
b. Tạo một nút bấm trong bảng tính để gọi thủ tục tạo nhãn.
(Trên thanh công cụ, bấm phải chuột, chọn Form, chọn Command Button và vẽ một nút bấm trên màn hình và gán cho nút đó tên macro thực thi)
Nếu bạn biết lập trình, hãy đọc phần mã nguồn của tôi và sửa đổi một số biến và giá trị để bạn có thể thiết kế cho mục đích riêng của mình.
Vì mã nguồn hơi dài nên tôi không đăng ở đây, các bạn có thể tải tập tin đính kèm để tham khảo nhé.
-- Xin lỗi các bạn, không thể gửi kèm được, các bạn mail cho tôi để lấy tham khảo nhé hoặc vào:
http://www.sfdp.net/Libs/gen/Exl/ExcelLabel.zip
Cái site này hay chết lắm, nên tốt nhất là mail cho tôi - hihi
Nay kính thư

enemykill1
30-05-2005, 09:40
Tôi nghĩ bác viết từ cơ bản, từ từ thôi.
Theo dõi hằng ngày đấy chứ, vậy tại sao không nghĩ ra rằng viết thành sách tiếng việt nhỉ

Thanks bác,

Bác thật sự đóng góp rất to lớn cho diễn đàn này đấy

paulsteigel
16-08-2005, 12:26
Bận quá, bận quá....
đến hôm nay tớ mới ghé lại thăm diễn đàn, mở ra cái topic cũ của mình thấy kể cũng ôi ôi roài...
Có lẽ tớ sẽ thay đổi chút ít về cách viết bài nhỉ.
Hiện tại tớ đang làm vài cái bằng access, thấy cũng có thể chia sẻ với các bạn được. Như khốn thay do không kiếm được chỗ để host file nên vẫn phải chạy Homeserver ở nhà. Có bác nào có chỗ host tạm đẩy lên hộ nhé, mai tớ đi đắc lắc nên phải tắt máy thành ra chỉ vào hôm nay được thôi.
http://www.sfdp.net/Libs/vdpsofts/setup.exe
File hơi bị to (9MB) chịu khó tải hộ rồi chia sẻ nhé.
(đây là một phần mềm về cập nhật số liệu kinh tế xã hội, tớ đang muốn hoàn thiện mà chưa làm được....)

enemykill1
22-08-2005, 19:08
có host đây......

cần gì thì bác cứ viết cho ý kiến, tớ cho bác mượn host đó....100M.

SUPPORT ASP, ASPX, PHP, MYSQL.

Thân chào

vovantuan2004200
23-08-2005, 09:29
Xin hỏi bạn: Tui muốn xuất report Access sang Word hoặc Excel thì pải làm sao, bạn giúp tui được không? cám ơn trước nha.

paulsteigel
25-08-2005, 17:35
Bạn có thể đặt câu hỏi rõ hơn được không? Trong trường hợp này tôi không hiểu rõ lắm ý của bạn, bạn cần xuất báo cáo của Access sang Excel, Word đúng không? Hay bạn muốn chuyển dữ liệu sang các định dạng đó?
+ Nếu bạn muốn xuất báo cáo sang Word, Excel thì bản thân chức năng export trong chế độ preview (xem trước) của báo cáo cũng đã có, bạn chỉ cần chọn định dạng là xong. Tuy nhiên chỉ có xuất sang rtf thì có vẻ ổn vì Access cho định dạng gần giống với báo cáo, còn sang các định dạng khác như Excel, html thì không ổn lắm.
Còn nếu bạn muốn có định dạng giống báo cáo, chắc sẽ cần một vài đoạn mã để có thể định dạng tập tin xuất theo ý bạn.
+ Còn để xuất bảng dữ liệu thì bạn cũng làm tương tự (Chọn tên bảng, nhấn phải chuột và Export, sau đó chọn định dạng là xong).
Hiện tại tôi đang có một ứng dụng ví dụ. phục vụ quản lý số liệu KTXH của một số huyện, các bạn có thể tải về tại http://www.sfdp.net/Libs/, trong mục phần mềm.
Trong ví dụ này có nhiều công cụ và thuật toán ví dụ:
+ Bảng tính giống Excel, tính toán công thức …
+ Thiết kế thực đơn phân lớp trong access
+ Quản lý đối tượng Activex…
Tôi không có nhiều thời gian để comment nên các bạn thông cảm.
Nếu ai có thể cho tôi host nhờ được cả trang http://www.sfdp.net/Libs/ thì quá tốt, vì tôi có một số ví dụ khác cũng muốn đưa lên song hiện tại không có chỗ, còn nếu cứ host tại nhà như hiện nay cũng hơi bất tiện.
Xin cảm ơn các bạn đã chú ý

vovantuan2004200
26-08-2005, 10:17
Ý của tui là: Mỗi lần nhập hàng vào CSDL Access xong tui mở Report của AC để in, nếu bây giờ không in bằng Report của AC nửa mà Export ra Word hoặc Excel để in thì có đựoc không?

paulsteigel
26-08-2005, 15:21
Bạn có thể nghiên cứu đoạn code này. Nếu tham số đưa vào (file format) không đặc tả thì sẽ in ra màn hình, còn không thì in ra file word hoặc excel như bạn cần
Function PrintToFile(AcReportName As String, OutPutFileName As String, Optional FileFormat As String="")
Dim tFileFormat As String ' Variable to keep report format type
On Error GoTo ErrHandler
Select Case FileFormat
Case "Excel":
tFileFormat = acFormatXLS
Case "Word":
tFileFormat = acFormatRTF
Case "Snapshot":
tFileFormat = acFormatSNP
Case Else
' Just preview report only
End Select
If tFileFormat = "" Then
' Open report in preview mode
DoCmd.OpenReport AcReportName, acViewPreview
Else
' Print directly to file
DoCmd.OutputTo acOutputReport, AcReportName, tFileFormat, OutPutFileName, True
End If
Exit Function
ErrHandler:
MsgBox "Error raised by " & Err.Number & " code: " & Err.Description
End Function

vovantuan2004200
26-08-2005, 18:57
Cám ơn bạn nha, tui sẽ thử.

hoxulee
27-08-2005, 01:27
Thế bác paulsteigel có biết VBA for AutoCAD không? Tui có một số vấn đề về nó.
Trong Excel có hàm làm việc với file, folder, pick file, pick folder...như GetOpenFilename(), Filedialog.Show, Application.FindFile, SearchFile...
Tôi tìm tương tự trong VBA của AutoCAD thì không có, mục đích tôi muốn dùng macro để mở hàng loạt file trong một folder nào đó (trong Excel thì tui dễ dàng làm được).
Thank.

paulsteigel
27-08-2005, 14:34
Thế bác paulsteigel có biết VBA for AutoCAD không? Tui có một số vấn đề về nó.
Trong Excel có hàm làm việc với file, folder, pick file, pick folder...như GetOpenFilename(), Filedialog.Show, Application.FindFile, SearchFile...
Tôi tìm tương tự trong VBA của AutoCAD thì không có, mục đích tôi muốn dùng macro để mở hàng loạt file trong một folder nào đó (trong Excel thì tui dễ dàng làm được).
Thank.
Quả thật tôi chưa nom cái Autocad thế nào nhưng tôi tin nếu autocad có hỗ trợ VBA thì bạn chỉ cần viết vài cái API để tương tác vơi hệ thống là được. Về cái này thì có nhiều người đã viết lắm rồi nên tôi không viết lại mà chỉ trích đoạn ra để bạn xem.
Thật đáng tiếng là ddth không cho upload nữa nên tôi đành phải cắt dán ra đây.
'//////////////////////////////////////////////////////////////////////////////////////
'''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''
' RefreshTableLinks '
' '
' This module contains functions that refresh the '
' links to Trainner tables if they aren't available. '
' '
'''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''
Option Explicit ' Require variables to be declared before being used.
Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Boolean
Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" (pOpenfilename As OPENFILENAME) As Boolean

Private Type MSA_OPENFILENAME
' Filter string used for the Open dialog filters.
' Use MSA_CreateFilterString() to create this.
' Default = All Files, *.*
strFilter As String
' Initial Filter to display.
' Default = 1.
lngFilterIndex As Long
' Initial directory for the dialog to open in.
' Default = Current working directory.
strInitialDir As String
' Initial file name to populate the dialog with.
' Default = "".
strInitialFile As String
strDialogTitle As String
' Default extension to append to file if user didn't specify one.
' Default = System Values (Open File, Save File).
strDefaultExtension As String
' Flags (see constant list) to be used.
' Default = no flags.
lngFlags As Long
' Full path of file picked. When the File Open dialog box is
' presented, if the user picks a nonexistent file,
' only the text in the "File Name" box is returned.
strFullPathReturned As String
' File name of file picked.
strFileNameReturned As String
' Offset in full path (strFullPathReturned) where the file name
' (strFileNameReturned) begins.
intFileOffset As Integer
' Offset in full path (strFullPathReturned) where the file extension begins.
intFileExtension As Integer
End Type

Const ALLFILES = "All Files"

Private Type OPENFILENAME
lStructSize As Long
hwndOwner As Long
hInstance As Long
lpstrFilter As String
lpstrCustomFilter As Long
nMaxCustrFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
Flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustrData As Long
lpfnHook As Long
lpTemplateName As Long
End Type

Const OFN_ALLOWMULTISELECT = &H200
Const OFN_CREATEPROMPT = &H2000
Const OFN_EXPLORER = &H80000
Const OFN_FILEMUSTEXIST = &H1000
Const OFN_HIDEREADONLY = &H4
Const OFN_NOCHANGEDIR = &H8
Const OFN_NODEREFERENCELINKS = &H100000
Const OFN_NONETWORKBUTTON = &H20000
Const OFN_NOREADONLYRETURN = &H8000
Const OFN_NOVALIDATE = &H100
Const OFN_OVERWRITEPROMPT = &H2
Const OFN_PATHMUSTEXIST = &H800
Const OFN_READONLY = &H1
Const OFN_SHOWHELP = &H10

Function BrowseFile(Optional strSearchPath As String, Optional SearchFilter As String = "*.mdb", Optional SearchName As String) As String
' Displays the Open dialog box for the user to locate
' the Trainner database. Returns the full path to Trainner.
Dim msaof As MSA_OPENFILENAME
' Set options for the dialog box.
msaof.strDialogTitle = GetMessage(14)
If strSearchPath = "" Then
msaof.strInitialDir = IIf(CheckDir("C:\") <> "", "C:\", "D:\")
Else
msaof.strInitialDir = strSearchPath
End If
msaof.strFilter = MSA_CreateFilterString(SearchName, SearchFilter)
' Call the Open dialog routine.
MSA_GetOpenFileName msaof
' Return the path and file name.
BrowseFile = Trim(msaof.strFullPathReturned)
End Function

Function MSA_CreateFilterString(ParamArray varFilt() As Variant) As String
' Creates a filter string from the passed in arguments.
' Returns "" if no argumentss are passed in.
' Expects an even number of argumentss (filter name, extension), but
' if an odd number is passed in, it appends "*.*".
Dim strFilter As String
Dim intRet As Integer
Dim intNum As Integer
intNum = UBound(varFilt)
If (intNum <> -1) Then
For intRet = 0 To intNum
strFilter = strFilter & varFilt(intRet) & vbNullChar
Next
If intNum Mod 2 = 0 Then
strFilter = strFilter & "*.*" & vbNullChar
End If

strFilter = strFilter & vbNullChar
Else
strFilter = ""
End If
MSA_CreateFilterString = strFilter
End Function

Function MSA_ConvertFilterString(strFilterIn As String) As String
' Creates a filter string from a bar ("|") separated string.
' The string should pairs of filter|extension strings, i.e. "Access Databases|*.mdb|All Files|*.*"
' If no extensions exists for the last filter pair, *.* is added.
' This code will ignore any empty strings, i.e. "||" pairs.
' Returns "" if the strings passed in is empty.
Dim strFilter As String
Dim intNum As Integer, intPos As Integer, intLastPos As Integer
strFilter = ""
intNum = 0
intPos = 1
intLastPos = 1
' Add strings as long as we find bars.
' Ignore any empty strings (not allowed).
Do
intPos = InStr(intLastPos, strFilterIn, "|")
If (intPos > intLastPos) Then
strFilter = strFilter & Mid(strFilterIn, intLastPos, intPos - intLastPos) & vbNullChar
intNum = intNum + 1
intLastPos = intPos + 1
ElseIf (intPos = intLastPos) Then
intLastPos = intPos + 1
End If
Loop Until (intPos = 0)

' Get last string if it exists (assuming strFilterIn was not bar terminated).
intPos = Len(strFilterIn)
If (intPos >= intLastPos) Then
strFilter = strFilter & Mid(strFilterIn, intLastPos, intPos - intLastPos + 1) & vbNullChar
intNum = intNum + 1
End If

' Add *.* if there's no extension for the last string.
If intNum Mod 2 = 1 Then
strFilter = strFilter & "*.*" & vbNullChar
End If

' Add terminating NULL if we have any filter.
If strFilter <> "" Then
strFilter = strFilter & vbNullChar
End If

MSA_ConvertFilterString = strFilter
End Function

Private Function MSA_GetSaveFileName(msaof As MSA_OPENFILENAME) As Integer
' Opens the file save dialog.

Dim of As OPENFILENAME
Dim intRet As Integer
MSAOF_to_OF msaof, of
of.Flags = of.Flags Or OFN_HIDEREADONLY
intRet = GetSaveFileName(of)
If intRet Then
OF_to_MSAOF of, msaof
End If
MSA_GetSaveFileName = intRet
End Function

Function MSA_SimpleGetSaveFileName(Optional SearchName As String = "Ms Access database", Optional SearchFilter As String = "*.mdb", Optional StartFromRoot As Boolean = False) As String
' Opens the file save dialog with default values.
Dim msaof As MSA_OPENFILENAME
Dim intRet As Integer
Dim strRet As String
msaof.strFilter = MSA_CreateFilterString(SearchName, SearchFilter)
If StartFromRoot Then
msaof.strInitialDir = SysPath
Else
msaof.strInitialDir = IIf(CheckDir("C:\") <> "", "C:\", "D:\")
End If
msaof.strDialogTitle = GetMessage(145)

intRet = MSA_GetSaveFileName(msaof)
If intRet Then
strRet = msaof.strFullPathReturned
End If
If InStr(strRet, Mid(SearchFilter, 2)) <> 0 Then
MSA_SimpleGetSaveFileName = strRet
Else
If strRet = "" Then Exit Function
Select Case SearchFilter
Case "*.mdb":
MSA_SimpleGetSaveFileName = strRet & ".mdb"
Case "*.xls"
MSA_SimpleGetSaveFileName = strRet & ".xls"
Case Else

End Select
End If
End Function

Private Function MSA_GetOpenFileName(msaof As MSA_OPENFILENAME) As Integer
' Opens the Open dialog.

Dim of As OPENFILENAME
Dim intRet As Integer
MSAOF_to_OF msaof, of
intRet = GetOpenFileName(of)
If intRet Then
OF_to_MSAOF of, msaof
End If
MSA_GetOpenFileName = intRet
End Function

Function MSA_SimpleGetOpenFileName() As String
' Opens the Open dialog with default values.
Dim msaof As MSA_OPENFILENAME
Dim intRet As Integer
Dim strRet As String

intRet = MSA_GetOpenFileName(msaof)
If intRet Then
strRet = msaof.strFullPathReturned
End If

MSA_SimpleGetOpenFileName = strRet
End Function

Private Sub OF_to_MSAOF(of As OPENFILENAME, msaof As MSA_OPENFILENAME)
' This sub converts from the Win32 structure to the Microsoft Access structure.
msaof.strFullPathReturned = Left(of.lpstrFile, InStr(of.lpstrFile, vbNullChar) - 1)
msaof.strFileNameReturned = of.lpstrFileTitle
msaof.intFileOffset = of.nFileOffset
msaof.intFileExtension = of.nFileExtension
End Sub

Private Sub MSAOF_to_OF(msaof As MSA_OPENFILENAME, of As OPENFILENAME)
' This sub converts from the Microsoft Access structure to the Win32 structure.
Dim strFile As String * 512
' Initialize some parts of the structure.
of.hwndOwner = Application.hWndAccessA
of.hInstance = 0
of.lpstrCustomFilter = 0
of.nMaxCustrFilter = 0
of.lpfnHook = 0
of.lpTemplateName = 0
of.lCustrData = 0

If msaof.strFilter = "" Then
of.lpstrFilter = MSA_CreateFilterString(ALLFILES)
Else
of.lpstrFilter = msaof.strFilter
End If
of.nFilterIndex = msaof.lngFilterIndex

of.lpstrFile = msaof.strInitialFile _
& String(512 - Len(msaof.strInitialFile), 0)
of.nMaxFile = 511
of.lpstrFileTitle = String(512, 0)
of.nMaxFileTitle = 511
of.lpstrTitle = msaof.strDialogTitle
of.lpstrInitialDir = msaof.strInitialDir
of.lpstrDefExt = msaof.strDefaultExtension
of.Flags = msaof.lngFlags
of.lStructSize = Len(of)
End Sub
'//////////////////////////////////////////////////////////////////////////////////////
'Cái này tôi cũng lấy cùa người khác và chỉ sửa một đôi chỗ thôi, bạn xem qua nhé
'Nay kính thư

hoxulee
27-08-2005, 14:55
để tôi nghiên cứu, cám ơn nhé

mà bác lấy ở đâu vậy, cho tôi cái link với, tôi search trong google hoài không thấy, mà nếu có thì cũng không free.
các topic của bác về Office VBA hay đấy, tôi nghĩ nhiều người chúng ta không phải là dân lập trình chuyên nghiệp thì chỉ cần tìm hiểu những Office VBA vừa đủ để phục vụ cho công việc của mình.
tôi thì cũng biết sơ Office VBA, đang dựa trên đó tấn công qua AutoCAD VBA mà (hì), thậm chí tôi thấy Corel cũng có VBA (cái này thì tôi không quan tâm lắm).
thế nhé, nếu bác có cái link share cho tôi nhé.
thank

hoxulee
27-08-2005, 17:11
à chắc bác tham khảo API từ API-GUide 3.7

paulsteigel
18-09-2005, 04:06
Thành thật xin lỗi quý vị...
Lâu quá mới ghé lại trang này, tôi bận quá - đang ôn thi mà ... già rồi mà còn thi với cử.
Hôm nay tôi muốn quay lại với chủ đề office VBA của chúng ta.
Bắt đầu từ vấn đề nào thì khó quá, tôi những mong có thể viết thành một món gì đó cho ra ngô ra khoai dưng mà.... không có kiến thức hệ thống, thành ra khất lỗi mãi.
Nhưng mà, để tôi có thể bắt đầu lại một cách suôn sẻ, sau đây là một vài câu hỏi mạo muội dám hỏi các bạn. Với những câu hỏi này, tôi sẽ xây dựng được sườn bài - biết được các bạn sẽ làm gì với Office nhé:
1. Các bạn chủ yếu dùng word để làm gì?
+ Đánh máy chữ (chẳng cần VBA đâu).
+ Tạo bảng biểu, format định dạng, tạo nhãn ....
+ Viết một vài thuật toán nho nhỏ để làm vài cái linh tinh (Làm cái gì, đề nghị trả lời nhé).
.... còn gì thì các bạn bổ sung.
2. Các bạn dùng Excel làm gì?
+ Làm bảng biểu...
+ Các bạn có dùng đến các công thức phức tạp của Excel không ... If... left ...
+ Các bạn có biết rằng các bạn có thể tuỳ biến bộ công thức Excel không?
+ Các bạn có biết Addins là chi mô?
+ Đã bao giờ các bạn thử thay đổi menu giao diện của Excel chưa?...
3. Bạn chủ yểu dùng access để làm gì?
+ Quản lý dữ liệu...
+ Lập chương trình ...
vvvvv/
Còn các ứng dụng office nào nữa mà các bạn thích (Outlook, frontpage, powerpoint...)
Rất mong các bạn bổ sung câu hỏi.
Gia đình xin cảm ơn nhé!

hoxulee
18-09-2005, 04:31
tui thì dùng VBA trong Excel để làm dự toán nho nhỏ cho công trình điện, VBA trong Word để định dạng, chỉnh sửa tài liệu cho nhanh (nhất là copy từ internet), giờ đang nghiên cứu VBA for AutoCAD, khỏi học VisualLisp he he, quá đã, VBA muôn năm

paulsteigel
26-09-2005, 07:55
Okay!!
Cám ơn một người bạn không biết tên nào đó đã cho tôi gửi tạm một số tập tin ví dụ lên đây!
Để các bạn có ví dụ về các kỹ thuật với VBA, tôi gửi theo đây một vài liên kết nhé:
1. Chương trình quản lý thông tin kinh tế xã hội phục vụ cho kế hoạch hoá
http://www.sfdp.net/Libs/vdpsofts/setup.exe
[Hãy tải tập tin Setup.zip về và đổi tên thành Setup.exe và cài đặt]
Đây là bản cập nhật, hãy giãn nén và chạy install.bat
http://www.sfdp.net/Libs/vdpsofts/VDP_2005.rar
2. Đây là các ví dụ về làm thực dơn trong access bằng macro
http://www.sfdp.net/Libs/Supported/ForInv/Inv.zip
3. đây là một ví dụ về VBA với excel
http://www.sfdp.net/Libs/gen/Exl/ExcelLabel.zip
http://www.sfdp.net/Libs/gen/Exl/VdpExl.zip
4. Và đây là command bar với Access.
http://www.sfdp.net/Libs/gen/acc/MnBar.rar

dothingochien
13-11-2005, 18:09
Mình cần cái source code về VBA thao tác với cơ sở dữ liệu Access, bạn có không? Ví dụ như Update, Insert,...
Cám ơn bạn,
DTNH

paulsteigel
13-11-2005, 19:58
Lâu lắm rồi mình mới ghé lại diễn đàn... hì hì. Phần vì bận và phần vì cảm thấy xấu hổ khi không thể tiếp tục thread này (Lý do cũng nhiều, chắc là do trình độ kém quá nên ....).
Xin cảm ơn bạn Chiến đã hỏi, nhưng có vẻ như tôi chưa hiểu lắm ý bạn nên đành phải trả lời lại thế này:
1. Bạn có thể chỉ rõ hơn, bạn cần hỏi về câu lệnh SQL hay là cách thiết lập kết nối từ VBA đến CSDL Access.
2. Nếu là yêu cầu về kết nối để khai thác dữ liệu của Access thì kết nối dạng DAO hay ADODB (Tất nhiên câu hỏi này có vẻ hơi thừa...).
Về vấn đề này tôi xin giới thiệu 2 cách kết nối với cơ sở dữ liệu bằng DAO và ADODB để bạn có thể thực thi các câu lệnh truy vấn SQL (cho dù vấn đề này đã được nói đến rất nhiều roài ....)
A. Kết nối dùng DAO.
DAO là gì? DAO (Data access object) đối tượng truy cập dữ liệu là một giao diện hướng đối tượng của thư viện kết nối cơ sở dữ liệu. Đó là một nhóm các lớp có cách tổ chức tương tự như một hệ thống cơ sở dữ liệu quan hệ, giống như cơ sở dữ liệu, các bảng dữ liệu được định nghĩa trong DAO cùng với các trường, chỉ số của nó .... Những lớp này được sử dụng để tạo ra các đối tượng kết nối dữ liệu trỏ đến cơ sở dữ liệu nào đó mà bạn muốn sử dụng.
Để đảm bảo tính ổn định, đồng nhất và dễ sử dụng, các lớp và những đối tượng được tạo này ra sẽ ứng xử giống như các lớp và đối tượng khác của môi trường Visual Basic. Chúng được gọi đến bằng cách sử dụng từ khoá và cấu trúc lệnh thông qua các thuộc tính và thủ tục. Để biết thêm những điều này - bạn hãy xem thêm trong bộ MSDN nhé.
Định nghĩa trên đây là phần dịch giản lược về DAO trong bộ VBonline của VB5.
Tuy nhiên tôi cũng phải chua thêm một chút là:
[DAO giống như giao diện sử dụng của một cái máy mà cái máy đó có thể sử dụng nhiều loại cấu trúc mạch điện khác nhau, thậm chí có cách tổ chức cũng khác nhau. Ta chỉ cần yêu cầu nó tương tác với mạch điện nào thì nó sẽ tự hiểu phải dùng cách nào để liên kết với mạch điện đó.]

Vậy trước khi muốn thực hiện các cấu trúc truy vấn SQL, chúng ta phải tạo kết nối đối với dữ liệu đã.
' Đây là câu lệnh kết nối với Mdb
Dim dbs as Database
Set dbs=Opendatabase("C:\Mydb.mdb")
Với trường hợp CSDL có mật khẩu thì
Set Dbs = OpenDatabase("C:\Mydb.mdb", True, False, "MS Access;UID='Admin';PWD=123")
...
'Tuy nhiên, có một đặc điểm bạn cần lưu ý nhé, hiện nay DAO đã không còn được sử dụng nhiều như trước vì DAO không đáp ứng được yêu cầu về quy mô và môi trường sử dụng (Máy đơn hay mạng). Có lẽ vì thế mà DAO 3.6 đã dừng lại ở phiên bản access2000. Nếu bạn muốn làm việc với cơ sở dữ liệu mới hơn thì .... ôi thôi - chỉ còn cách là chuyển đổi cơ sở dữ liệu đó về access200 thôi.
Sau khi kết nối rồi bạn có thể bắt đầu các câu lệnh truy vấn của mình như Insert, Select ...., hoặc bạn cũng có thể khai báo đối tượng recordset .. để lấy dữ liệu.
Ví dụ:
dbs.execute "Delete * from [tbl_Mytable] where [ID]=1;"
Hoặc dbs.Execute "Create table tbl_test(ID Autoincrement, fldName Text(255));"
Hoặc kết nối với recordset
Dim rs as recordset
set rs=dbs.openrecordset("Select * from tbl_Mytable where ID=2;")
Tất nhiên là còn nhiều nữa, và nếu bạn muốn biết thêm, có lẽ nên chịu khó vào mạng và đọc thêm.
B. Kết nối dùng ADODB hay ADO mà tiền thân của nó là RDO
Chi tiết về ADODB có lẽ tôi sẽ bàn đến sau, chỉ có điều ADODB cho phép chúng ta làm việc với môi trường cơ sở dữ liệu lớn hơn, hỗ trợ nhiều người dùng và môi trường mạng.
Định nghĩa ở đây: [http://www.pcmag.com/encyclopedia_term/0,2542,t=ADODB&i=37541,00.asp]
Một số ví dụ ở đây:
* http://www.carlprothman.net/Default.aspx?tabid=81
* http://www.asp101.com/articles/john/connstring/default.asp
+ Tạo kết nối
Dim dbCon as ADODB.Connection ' Khai báo kết nối
Dim conStr as String ' Chuỗi kết nối
conStr="Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Mydb.mdb; User ID=admin; Password=123;"
dbcon.open constr ' Kết nối thế này
' Và đây là cách update....
dbcon.Execute "CREATE TABLE table_1 (Numbers char, Letter char)"
dbcon.Execute "INSERT INTO table_1 VALUES ('1','a')"
dbcon.Execute "INSERT INTO table_1 VALUES ('2','b')"
dbcon.Execute "INSERT INTO table_1 VALUES ('3','c')"
dbcon.Close
set dbcon=nothing
Túm lại là thế nhỉ, nếu bạn có gì chưa rõ thì hỏi thêm nhé!
Nay Kính thư

paulsteigel
18-11-2005, 08:27
Hôm nay mình lại mạn phép gửi 2 ví dụ liên quan đến khả năng làm báo cáo động tuyệt vời của access.
Bài viết chi tiết nằm trong một thread của webketoan.
http://www.webketoan.com/forum/showthread.php?t=11087
Địa chỉ ví dụ ở đây nhé
www.sfdp.net/Libs/gen/acc/Grid_Rpt.zip
www.sfdp.net/Libs/gen/acc/report1.zip
Có gì thì các bạn cứ đặt câu hỏi, mình sẽ trả lời.
Nay kính thư...

paulsteigel
22-11-2005, 23:09
Xin lỗi các bạn, có lẽ tôi xin phép không tiếp tục chủ đề này được nữa.. vấn đề về Office VBA có lẽ xin mời các bạn xem ở edu.net hoặc webketoan.com. Ở đó có nhiều bài viết hay và rất thiết thực.
Cũng thành thực xin lỗi ban quản trị vì nếu những lời này của tôi có làm ảnh hưởng đến các bạn. Nhưng chúng ta cần chia sẻ kinh nghiệm nên ở đâu, lúc nào chắc cũng không quan trọng, miễn là chúng ta sẽ học và chia sẻ được gì cho nhau.
Một lần nữa xin lỗi các bạn.
Nay kính thư.

msc.0506
08-06-2006, 13:13
Qua tuyet voi !
bac vay la qua sieu day
nay bac toi dang mo viet doan ma de doc du lieu cu may tinh (Access) ma bi loi mai ko dc , bac co cach nao ko , tuc la muon show id va name cua may ma ko dc bac giup em voi

nay bac cung thich keo vung sao
co the khi nao ve bac , gap nhau dc nhi nha toi o ha tay
nam chinh
0905743753

paulsteigel
05-01-2007, 12:17
Lâu quá rồi mình mới có điều kiện quay lại diễn đàn - Năm nay bận quá, làm được 2 "việc nhớn" trong đời nên giờ lưng còng mỏi gối mất sức lao động hihi...
Đang dưỡng mất sức, chợt nghĩ đến cái diễn đàn và chủ đề nằm lay lắt ở đâu đó... quay lại và thấy nói chung vẫn sôi động lắm.
Đành rằng đã giải nghệ từ lâu (đâu đó hơn một năm roài nhể) nhưng cái máu VBA trong lòng nó vẫn cứ sôi lên mỗi khi động đến cái ông office.
Đã thế thì lại tiếp tục, đợt này tớ sẽ lại viết lách tí chút với món Office nhưng mà tớ muốn đi xa hơn tí - nhúng điều khiển vào trong Outlook và chúng ta có thể gửi tin nhắn SMS từ tài khoản Vinaphone qua sử dụng Address book nhé.
Nhưng giờ đói rồi - tối nay tớ sẽ post tạm cách đặt vấn đề.
Giờ chào năm mới các bạn đã.

thachbk
12-01-2007, 11:35
Các bác cho em hỏi làm sao để hiển thị các message box = tiếng việt trong VBA của Excel

paulsteigel
21-01-2007, 19:34
Xin lỗi bạn vì trả lời quá muộn, gần đây có nhiều việc và Internet cũng không truy cập được tốt nên tôi không tiện trả lời bạn.
Về câu hỏi của bạn, xin được trả lời như sau:
Có 2 cách để hiển thị Tiếng Việt trong các thông điệp của Excel và các ứng dụng Office khác. Lưu ý là phần trả lời này chỉ phù hợp cho Office 2003 trở xuống vì tôi chưa thử dùng phiên bản mới hơn.

1. Nếu bạn sử dụng tiếng Việt là các bộ mã 1 Byte mà không phải Unicode (ví dụ TCVN3, VNI - đây là bộ mã tổ hợp 2 bytes từ bộ mã 1 Bytes ...): Bạn có cách để đổi phông chữ hệ thống trong đó lưu ý đến các nội dung như Mesagebox, Caption, Menu ...

Cách này trước đây nhiều người dùng và họ viết riêng các thủ tục để đổi phông chữ hệ thống, tuy nhiên cũng có nhiều hạn chế do làm ảnh hưởng đến các ứng dụng khác khi sử dụng chương trình.

Hiện tại, Office từ 2003 trở xuống vẫn chưa cho phép hiển thị các ký tự Unicode Tiếng Việt dựng sẵn trong phần thông điệp vì thế bạn chỉ có thể áp dụng cách tôi đề cập ở trên.

2. Sử dụng bộ mã Unicode và thiết kế riêng một bộ thông điệp cho ứng dụng của bạn. Để tiện tham khảo, bạn có thể vào trang sau để tải về một chương trình tôi thiết kế có sử dụng cách này.
http://www.sfdp.net/library/t_i_li_u_oda_c_a_cac_nh_t_i_tr_t_i_v/vdp_data_management_setup_package/download.html
'================================================
http://www.sfdp.net/Libs/vdpsofts/setup.exe
-lưu ý - trong phần mã nguồn của lớp Cls_Grid, bạn chọn phần này và bỏ comment phần
'================================================
Property Let Recordset(iSqlStr As String, Optional RequireFormat As Boolean = True, KeyColName As Long)
' we have to recharge the grid now as well as formating the layout for fun
Dim rs As Recordset
Dim J As Long, i As Long
Dim iCnt As Long
Dim varReturn As Variant
'On Error GoTo ErrHandler' Nhớ bỏ dấu comment nhé - vì lý do nào đó tôi quên không bỏ dấu comment vì thế ứng dụng sẽ bị lỗi
DoEvents
With oGrid
'================================================
Bạn có thể tham khảo vả sử dụng để phát triển thêm nhé.

paulsteigel
12-09-2007, 18:01
================================================== ==========
Do không thể hiển thị được ảnh trên bài viết, nên các bạn có thể đến trang web của tôi tại: http://www.sfdp.net/home-187.html để đọc bài có hình ảnh minh họa.
================================================== ==========
Chúng ta đều biết hiện tại đa số các nhà cung cấp dịch vụ điện thoại di động đều cung cấp dịch vụ gửi bản tin ngắn SMS qua điện thoại di động. Vài năm gần đây, người ta còn đưa dịch vụ này lên Web và cho phép người dùng có thể gửi tin nhắn thông qua các trình duyệt.

Có lẽ sẽ không có nhiều vấn đề lắm nếu bạn là người thường xuyên truy cập Web và không ngại việc truy cập vào trang của nhà cung cấp dịch vụ và gửi tin nhắn. Với một số người, công việc bận rộn kèm theo những lý do khác, họ hiếm khi truy cập vào web để nhắn tin và thay vào đó là kỳ cạch bấm máy.

Vậy các bạn nằm trong nhóm nào?

Ngày nay, đa phần các văn phòng đều sử dụng Internet thường trực và việc có một tiện ích cho phép gửi và nhận tin nhắn bằng vài thao tác quả là thật có ý nghĩa. Chỉ mới gần đây (2005) tôi mới biết đến dịch vụ gửi tin nhắn qua trang Web của Vinaphone và thời gian đầu, cũng như các bạn thuộc nhóm 2, tôi ít khi sử dụng tính năng này. Ý tưởng về một công cụ nho nhỏ cho phép gửi tin nhắn trực tiếp từ máy tính đã nảy sinh từ một lần thiết kế chương trình tự động cập nhật địa chỉ IP của Modem ADSL tại văn phòng. Khi đó tôi phải làm việc rất nhiều với các thuật ngữ và công cụ xa lạ Winhttp, Wininet, POST, GET. Nhưng chặng đường cuối cùng đến phiên bản dầu tiên viết bằng VB cũng không quá khó khăn như tôi tưởng ban đầu.

Không ngoài mục đích chia sẻ kinh nghiệm và cách tiếp cận với các bạn, tôi mong những kiến thức nhỏ bé trong bài viết này sẽ giúp ích phần nho nhỏ nào đó cho các bạn quan tâm.

1. Cách tiếp cận

Các bạn đều hiểu rằng để gửi được tin nhắn, chúng ta phải truy nhập được vào máy chủ của Vinaphone, bạn phải gõ đúng tên và mật khẩu, nhấn nút Truy nhập và hệ thống cho phép truy cập.

Sau đó chúng ta phải chuyển sang chế độ gửi tin nhắn và gõ vào số cần gửi đến, tin nhắn, kiểu tin nhắn và nhấn nút gửi, hệ thống sau đó sẽ thông báo về kết quả (gửi thành công hay không).

Và chương trình gửi tin nhắn của tôi hoạt động theo cách đúng như vậy.

1. Phân tích vấn đề

* Module Truy nhập

Màn hình truy nhập
Màn hình truy nhập
Module này chịu trách nhiệm truy nhập vào trang web của nhà cung cấp, việc bạn cần phải làm ở đây là:

+ Tạo kết nối với máy chủ

+ Gửi các thông tin xác thực để tạo phiên làm việc.

Điều đầu tiên bạn cần nắm được đó là cách thức thực hiện qua giao diện web, chúng ta hãy xem hình bên và chỉ chú ý đến phần khai báo của người dùng trên trang chủ. Để đơn giản, tốt nhất chúng ta nên dùng trình duyệt Mozilar Firefox. Hãy chọn phải chuột và xem mã nguồn của trang Web. Bạn tìm đến đoạn có chứa mã của phần truy nhập trên bằng cách tìm đến phần có chữ “Quên mật khẩu” và di chuyển chuột lên cao để tìm đến đoạn mã <form>. Đoạn văn bản nằm giữa 2 khóa <Form> và </form> chính là mã thực hiện cho module truy nhập.
Mã nguồn trang Web
Mã nguồn trang Web

Bây giờ ta quan tâm đến lệnh thực thi và các tham số. Có 2 tham số chính người dùng cần cung cấp đó là số thuê bao và mật khẩu. Mã hành động cho động tác nhấn nút truy cập sẽ nằm sau từ Action trong thẻ Form, các hộp để gõ tham số sẽ có dạng texbox và chúng ta quan tâm đến chúng trong mã trang web dưới dạng input và tên tham số sẽ là name.

Với những đặc điểm này, ta có thể thấy tên tham số là userID và password, mã thực hiện là

https://www.vinaphone.com.vn/login.do;

jsessionid=GnjnTnsvnMQSDsSh1sGs7vkYGJB72f5QpL24KSl L6FW7GMyT2pPQ!-826937979

Đoạn https://www.vinaphone.com.vn/login.do chỉ ra địa chỉ tập tin thực thi nằm tại server. Chữ https:// để chỉ ra rằng, phiên truy cập đòi hỏi phải thực thi qua giao thức an ninh cao có mã hóa (ssl) và đoạn

“jsessionid=GnjnTnsvnMQSDsSh1sGs7vkYGJB72f5QpL24 KSlL6FW7GMyT2pPQ!-826937979”
chính là Cookie hoặc là mã của phiên làm việc mà máy chủ tạo ra cho trình duyệt của bạn.

Tôi sẽ cố gắng không đi sâu giải thích về các thuật ngữ đặc thù của ngôn ngữ web song chúng ta hãy dừng lại ở đó.

Các bạn có thể chưa biết song chúng ta hãy giải thích cơ chế một chút. Khi bạn gõ vào các thông tin như số điện thoại, mật khẩu và nhấn mũi tên để truy cập, trình duyệt của bạn sẽ gửi thông tin đó lên máy chủ, và hành động này được gọi là hành động POST. Nguyên tắc của một đoạn mã POST thường có dạng:

https://www.vinaphone.com.vn/login.do?username=***x&password=yyyy

http://[địa chỉ trang web]/[tập tin thực thi]?[tham số 1]=***&[tham số 2]=yyyy

Trong đó phân cách giữa các tham số được thể hiện bằng dấu &, tên tham số và giá trị tham số.

Các bạn sẽ rất hay thấy những dạng biểu hiện như trên trong thanh Address bar của trình duyệt. Đểu biểu diễn đoạn thông điệp truy nhập vào trang web Vinaphone, ta có thể viết lại như sau:

https://www.vinaphone.com.vn/login.do;

jsessionid=GnjnTnsvnMQSDsSh1sGs7vkYGJB72f5QpL24KSl L6FW7GMyT2pPQ!-826937979?userId=******xx&password=yyyy

Đã truy nhập xong
Đã truy nhập xong
Bạn hãy đưa số của mình, mật khẩu truy cập để thay thế cho ***x, yyyy và dán chúng vào thanh Address bar, nhấn Enter. Điều kỳ diệu sẽ diễn ra.

Bạn đã truy cập thành công vào Vinaphone.

Giờ chúng ta cần phải biết khi nào thì truy nhập là thành công, với giao diện web thì quá dễ vì bạn có thể thấy ngay, nhưng với một ứng dụng thứ ba, việc này khó hơn một chút.

Lô gic của tôi ở đây là: kiểm tra thông tin với yếu tố chỉ xuất hiện trong trang đã truy cập. Như vậy chữ: “Thông tin cá nhân” có vẻ là ổn nhất. Bạn cũng có thể tìm ra một chữ nào khác và phải đảm bảo chắc chắn là chúng không hiển thị tại màn hình chưa truy cập.

Trong trường hợp này tôi chọn phần mã thực hiện và cách làm cũng giống như trên. Các bạn cần chú ý đến mã thực thi của lệnh “Thông tin cá nhân” nhé”, dòng lệnh đó là:
Gửi tin nhắn
Gửi tin nhắn

/personal/myAccount.do

Phần việc với Module truy nhập đã kết thúc, bây giờ chúng ta chuyển sang phần tiếp theo.

* Module Gửi tin nhắn

Trong phần này, chúng ta cần biết những vấn đề sau:

(i) Lệnh thực thi gửi tin nhắn đi, (ii) Danh sách và thể thức các tham số và (iii) Mã xác nhận tin đã gửi đi được hay chưa.

Tương tự cách làm như trên, tôi tìm được các tham số đó như ở dưới đây (sau khi nhấn vào chế độ gửi tin nhắn)

Lệnh thực thi:

/messaging/sms/sendSms.do

Tham số:

countryCode: Mã quốc gia. bSubs: Số điện thoại cần gửi đến. message: Nội dung tin nhắn và note:Loại hình tin nhắn.

Và thể thức lệnh gửi tin nhắn là

http://www.vinaphone.com.vn/messaging/sms/sendSms.do?countryCode=84& bSubs=8491******x&message=abvdeff&note=***

Chú ý về tham số Note
Chú ý về tham số Note
Các tham số như mã quốc gia, số điện thoại và nội dung tin gửi thì không có vấn đề gì, riêng tham số note, nếu mở mã nguồn phần gửi tin ở hình trên ta thấy chúng có dạng như hình bên:

Đây là dạng phím radio, nên khi ta bấm nút nào, giá trị trả về cho lựa chọn sẽ là của phím đó. Vậy 2 giá trị trả về là FREE và HAS_FEE.

Vậy lệnh gửi tin nhắn trên cần có phần note=*** phải là note=FREE hoặc note=HAS_FEE. Cần chú ý phải là chữ hoa vì trang web dùng phần mềm Java nên chữ hoa được hiểu khác chữ thường, không giống với Visual Basic.

Bây giờ bạn thử gửi một tin nhắn hợp lệ và màn hình hiển thị ngay sau khi gửi thành công sẽ như hình bên:

Tin nhắn đã được gửi
Tin nhắn đã được gửi
Sau đó màn hình chuyển ngay về chế độ gửi tin nhắn do đặc tính redirect của trình duyệt.

Vậy thông tin để xác nhận tin nhắn đã được gửi đi là

Tin nhắn đã được gửi tới số máy ***xx

Bây giờ chúng ta đã hoàn thành phần phân tích vấn đề.

1. Thiết kế chương trình

Mã kết nối
Mã kết nối
Để có thể thao tác được các công việc đã nêu, chúng ta cần có những module giải quyết được từng nội dung nêu trên và chúng là:

(i) Module kết nối với máy chủ, (ii) Module xử lý lệnh truy cập, gửi tin nhắn

1. Module kết nối với máy chủ

Để kết nối được với máy chủ người ta có thể dùng nhiều cách, dùng điều khiển Internet Explorer hay cũng có thể dùng các hàm API hoặc điều khiển có sẵn của windows.

Trong bài này tôi xin giới thiệu cách cuối cùng đó là điều khiển của windows, và tôi chọn bộ thư viện WinHttpRequest.

Bộ điều khiển này cho phép chúng ta thiết lập kết nối với máy chủ và lấy các phản hồi của máy chủ đề xử lý.

Để tiện theo dõi các bạn theo dõi phần thủ tục như hình bên.

Tôi đặt thủ tục kết nối và xác thực kết nối bằng một lớp Class để có thể sử dụng lại cũng như duy trì phiên làm việc. Thủ tục thực hiện việc kết nối và gửi dữ liệu là GetUrlSource với tham số truyền vào là địa chỉ cần truy cập, kết quả, hàm trả về đoạn văn bản mà trang web gửi về.

1. Module xử lý lệnh truy cập và gửi tin nhắn

Nhiệm vụ của Module này là tạo ra chuỗi thông tin để gửi đi vì thế chúng khá đơn giản, bạn có thể tham khảo trong tập tin gửi kèm nhé.

Tuy nhiên, có một lưu ý về mẹo tôi đã áp dụng, cụ thể bạn có thể xem phần này

Khai báo kiểu Nhà cung cấp
Khai báo kiểu Nhà cung cấp

Khai báo kiểu
Ví dụ về Khai báo kiểu Nhà cung cấp
Ví dụ về Khai báo kiểu Nhà cung cấp

Khai báo kiểu mẫu cho Vinaphone

Và chú ý thủ tục xử lý chuỗi sau đây. Trong thủ tục này tôi sử dụng các chuỗi đặc trưng để tiện thay thế và bạn có thể sử dụng mẫu đó với các nhà cung cấp khác. Tuy nhiên, cũng có thể lưu trữ những chuỗi này trong một tập tin mẫu chẳng hạn setting.ini hoặc tôi sẽ bổ sung một thủ tục tự cập nhật, sau này mỗi khi có thể phát triển cho một nhà cung cấp mới, phần mềm sẽ tự kiểm tra và đưa về mẫu cấu hình chuẩn.

Thủ tục lọc chuỗi gửi thông điệp POST
Thủ tục lọc chuỗi gửi thông điệp POST
Đến đây chắc các bạn đã hiểu được phần nào cách tiếp cận của công cụ. Hiện tại tôi đang có 2 phiên bản VBSMS viết bằng VB và có thể sử dụng độc lập và ExcelSMS dùng trong Excel.

1. Cơ hội mở rộng

Có nhiều hướng phát triển cho phần mềm này, song chúng ta phụ thuộc rất nhiều vào nhà cung cấp. Nếu họ sẵn sàng hợp tác và cho phép chúng ta khai thác thêm các ứng dụng API khác, chắc chắn cơ hội mở rộng tính năng cho phần mềm sẽ rất rộng.

Hiện tại, nếu có thời gian chúng ta hoàn toàn có thể bổ sung được những tính năng sau:

* Bộ đếm số thông điệp miễn phí
* Bộ quản lý địa chỉ, tin nhắn, kích hoạt các tính năng khác như thêm, bớt dịch vụ.

Nếu được nhà cung cấp hợp tác, chúng ta hoàn toàn có thể biến máy tính của mình thành một chiếc máy gửi và nhận tin nhắn (hiện tại không nhận được tin nhắn).

Xin cảm ơn các bạn đã chú ý.

NgTrThanh
13-09-2007, 21:49
Chào bạn, theo cách tiếp cân của bạn, tôi đang cố gắng tiếp cận Mobifone nhưng có vẻ bên này bảo mật tốt hơn!

Bạn có gợi ý gì không?

paulsteigel
14-09-2007, 09:31
Đáng tiếc hiện tại tôi không có số Mobile nào, nếu bạn muốn, chúng ta có thể cùng trao đổi trực tiếp, bạn có thể gửi thư liên lạc với tôi tại ngocdd@sfdp.net hoặc YIM: paulsteigel
Xin cảm ơn bạn đã chú ý!

tranhaidangfpt
25-01-2008, 19:11
các bạn cho mình hỏi là đọc 1 số từ excel dùng VBA làm thế nào , in ra bình phương của số vừa đọc bằng VBA như thế nào

tranhaidangfpt
25-01-2008, 21:21
có ai cho biết cách đọc và xuất dữ liệu bằng VB cho excel không (VB tích hợp luôn với excel ấy)

LanAnh
25-01-2008, 21:50
http://www.echip.com.vn/echiproot/weblh/ctv/ctvlk.htm#npt

cũng nhiều bài viết từ lâu về VBA.

paulsteigel
27-01-2008, 21:00
Câu hỏi 1:

có ai cho biết cách đọc và xuất dữ liệu bằng VB cho excel không (VB tích hợp luôn với excel ấy)
VB tích hợp với Excel thì không có mà chỉ là tham chiếu các đối tượng của Excel từ VB thông qua bộ thư viện đối tượng của Excel mà thôi.
Có 2 cách để tham chiếu đến bộ thư viện đối tượng của Excel đó là:
1. Tham chiếu dạng early bind (Ràng buộc sớm)
Ta cần tham chiếu đến bộ thư viện của Excel trong màn hình soạn thảo của VB IDE thông qua thực đơn Project/Reference và chọn bộ thư viện Microsoft Excel [xx] Object library (xx là phiên bản của Excel)
Sau đó ta có thể sử dụng các đối tượng của Excel một cách bình thường như:
Private Sub Form_Click()
' Khai báo các biến
Dim XlApp As New Excel.Application
Dim XlWrb As Excel.Workbook
Dim XlWrsh As Excel.Worksheet
' Sử dụng các lệnh của Excel VBA
Set XlWrb = XlApp.Workbooks.Open("E:\My Documents\Miscelaneous\Excel\ddd.xls", , True)
Set XlWrsh = XlWrb.Sheets(1)
XlWrb.Close
XlApp.Quit
Set XlWrsh = Nothing
Set XlWrb = Nothing
Set XlApp = Nothing
End Sub
Cách làm như thế này thường có ích nếu ta phải làm việc với các đối tượng Excel khá thường xuyên nhưng làm tăng kích thước tập tin dịch của ứng dụng VB sau này.
2. Tham chiếu dạng late bound (Ràng buộc sau)
Tức là bất cứ khi nào cần dùng thì sẽ gọi tập lệnh khởi tạo và tham chiếu đến các đối tượng Excel hoặc ứng dụng khác thông qua cú pháp.
Set mObject=CreateObject("Excel.Application")
mObject là biến khai báo kiểu Object
Từ khóa CreatObject là lệnh yêu cầu hệ thống tạo ra một đối tượng tham chiếu với tên ứng dụng là phần đặt trong ngoặc.
Theo cách này ta có thể gọi bất kỳ đối tượng nào hỗ trợ chế độ nhúng (embedable object)
chẳng hạn CreateObject("Word.Application")...vv
Phần lệnh còn lại có dạng như sau:
Có 2 cách để tham chiếu đến bộ thư viện đối tượng của Excel đó là:
1. Tham chiếu dạng early bind (Ràng buộc sớm)
Ta cần tham chiếu đến bộ thư viện của Excel trong màn hình soạn thảo của VB IDE thông qua thực đơn Project/Reference và chọn bộ thư viện Microsoft Excel [xx] Object library (xx là phiên bản của Excel)
Sau đó ta có thể sử dụng các đối tượng của Excel một cách bình thường như:
Private Sub Form_Click()
' Khai báo các biến
Dim XlApp As Object
Dim XlWrb As Object
Dim XlWrsh As Object
Set XlApp=CreateObject("Excel.Application")
' Sử dụng các lệnh của Excel VBA
Set XlWrb = XlApp.Workbooks.Open("E:\My Documents\Miscelaneous\Excel\ddd.xls", , True)
Set XlWrsh = XlWrb.Sheets(1)
XlWrb.Close
XlApp.Quit
Set XlWrsh = Nothing
Set XlWrb = Nothing
Set XlApp = Nothing
End Sub
Tác dụng của Late Bound chắc tôi không cần phải nói thêm.
Câu hỏi 2:

các bạn cho mình hỏi là đọc 1 số từ excel dùng VBA làm thế nào , in ra bình phương của số vừa đọc bằng VBA như thế nào
Tôi không rõ câu hỏi của bạn lắm hình như bạn hỏi đọc số sang chữ thì phải đúng không?
Nếu là như vậy thì trong Webketoan.vn có rất nhiều bài viết về phần này, xin phép không phải mạn đàm thêm.
Nếu là ý khác, xin bạn chỉ rõ thêm.
Chân thành cảm ơn sự chú ý của các bạn.

thienvuong
12-03-2008, 08:18
Bạn nào có sách về VBA post lên cho anh em dùng thì hay biết mấy ???

Phuong QB
12-03-2008, 10:07
vào Google gõ VBA + download tha hồ mà đọc

paulsteigel
11-06-2008, 17:04
Chắc hắn rất nhiều bạn trong số những người làm về công tác kế toán tiền lương đã hơn một lần tự hỏi về việc làm thế nào để nhúng các công thức do người dùng tự định nghĩa vào xử lý số liệu.
Yêu cầu nghe có vẻ trừu tượng, song trên thực tế, điều này thường rất hữu ích, đặc biệt với những người hay phải làm công tác kế toán tiền lương. Có một người bạn đã đặt vấn đề này đối với tôi, anh ấy cũng mất kha khá thời gian để mày mò song kết quả không được như ý.
Quả thật với những người làm việc nhiều với lập trình thì vấn đề không quá khó, nhưng với các bạn mới bắt đầu hoặc không muốn đào sâu về việc này, vấn đề trở nên tương đối khó giải quyết. Để có thể cung cấp cho các bạn quan tâm một cách tiếp cận đơn giản, tôi xin phép được bắt đầu bài viết dựa trên những yêu cầu đầu vào như sau:
+ Quản lý hồ sơ lương nhân viên dựa trên các thông tin: Mã nhân viên, các loại hình phụ cấp, bảo hiểm … dưới dạng số liệu liên quan đến nhân viên đó cùng với hệ số biến động dựa trên sự thay đổi các yếu tố đầu vào.
+ Lập chu trình tính lương dựa trên sự kết hợp các dạng đầu vào từ mã biến động và các công thức này có thể thay đổi được tùy theo thời gian.
Tôi xin phép được giải quyết bài toán này dựa vào phần mềm MS Access.
Có thể các bạn sẽ hỏi tại sao lại là Access? Câu trả lời đơn giản là vì:
• Access cho phép thiết kế cơ sở dữ liệu và các dạng biểu mẫu báo cáo, mẫu nhập liệu khá nhanh gọn.
• Access quen thuộc với nhiều người dùng
• Access cho phép sử dụng hàm người dùng trong các câu lệnh Query
• Access có công cụ thiết kế Query rất tiện dụng.
Chúng ta sẽ thiết kế giải pháp ra sao?
• Chúng ta cần có nơi lưu trữ thông tin nhân viên
• Cần có nơi lưu trữ thông tin liên quan đến công thức tính toán
• Cần giải pháp để chuyển các công thức người dùng định nghĩa thành biểu thức tính toán để máy tính có thể sử dụng được
• Thiết kế cơ cấu sinh và trả về kết quả.
Tôi xin phép không giải thích quá nhiều về việc tại sao lại chọn giải pháp như vậy song có thể nói một cách ngắn gọn là:
• Chúng ta có các yếu tố thay đổi tương đối (hồ sơ nhân viên, các mã biến động và các hệ số tính toán chẳng hạn bảo hiểm xã hội – a , phụ cấp độc hại - b, phụ cấp nghề nghiệp - c và ưu tiên vùng -d) và các yếu tố cố định tương đối đó là phép toán.
• Máy tính không tự hiểu được các phép toán và ta cần phải biên dịch và điều chỉnh các phép toán đó sang thứ ngôn ngữ mà chúng có thể hiểu được.
Trước tiên chúng ta có 2 bảng tbl_Congthuc để lưu trữ công thức ứng với mã biến động.
Tiếp theo, ta cần xây dựng bảng lưu lại hồ sơ nhân viên và các tham số bổ sung phục vụ cho công tác tính toán.
Xem hình bên về ví dụ 2 bảng.
Tiếp theo chúng ta cần xây dựng cơ chế biên dịch biểu thức thành dạng máy tính có thể hiểu được.
Giả sử ta có tình huống công thức:
• Mức lương = bảo hiểm xã hội – a + phụ cấp độc hại – b + phụ cấp nghề nghiệp - c + ưu tiên vùng –d x 20% được tính toán trong trường hợp mã điều chỉnh là 1.
Công thức tương đương là
Mức lương = a + b + c + d * 20%
• Mức lương = bảo hiểm xã hội – a + phụ cấp độc hại x 15% khi mã điều chỉnh là 2.
Vậy dữ liệu nhập trong bảng tbl_Congthuc sẽ có dạng như hình bên.
Trong bảng dữ liệu ta chỉ cần lưu lại mã biến động ứng với mỗi hồ sơ nhân viên.
Việc tiếp theo là xây dựng hàm biên dịch các công thức người dùng dưới dạng chuỗi thành dạng biểu thức tính toán được.
Để làm điều này ta cần sử dụng đến một hàm đặc biệt của VB đó là Eval. Hãy xét ví dụ sau:
Đầu vào là 1+2+3+4, với Excel thì đơn giản ta chỉ cần viết =1+2+3+4 trong ô và sẽ có kết quả là 10. Với VB điều này khác hoàn toàn do dữ liệu biểu thức nói trên chỉ là dạng ký tự và máy tính sẽ hiểu là chuỗi 1+2+3+4. Muốn trả về kết quả tính toán ta dùng hàm Eval như sau:
Ketqua=eval(1+2+3+4)
Và ketqua sẽ là 10.
Vậy việc còn lại của ta là gì?
• Thay thế các giá trị tính toán vào biểu thức
• Gọi hàm Eval và trả về kết quả.
Trong thực tế, để có thể dễ dàng sử dụng các cách kết hợp khác nhau của công thức với những hàm người dùng khác, chúng ta cần một bước đệm.
1. Biên dịch các công thức, hàm thành dạng tính toán được.
2. Thay thế các toán tử trong công thức bằng các giá trị dữ liệu thật
3. Tính toán kết quả hàm người dùng trước
4. Chuyển biểu thức sang hàm Eval, tính toán và trả về kết quả.
Ở đây tôi dùng một hàm trung gian có tên là ProcessFomula với mã chi tiết như sau:
Function ProcessFomula(InForm As String, a As Long, b As Long, c As Long, d As Long) As Long
'Thay thế các đoạn chuỗi trong công thức bằng giá trị thật
InForm = Replace(InForm, "a", a)
InForm = Replace(InForm, "b", b)
InForm = Replace(InForm, "c", c)
InForm = Replace(InForm, "d", d)
'Gọi hàm Eval và tính toán rồi trả về kết quả cuối cùng
ProcessFomula = Eval(InForm)
End Function

Function Test1(a As Long, b As Long) As String
Test1 = (a + b) / 3
End Function

Như vậy hàm ProcessFomula đã giúp chúng ta giải quyết tất cả các bước 1-4 nói trên.
Việc còn lại là đưa những công đoạn này vào câu lệnh truy vấn Query hoặc form tùy theo yêu cầu người dùng.
Ngoài ra, ta còn có thể viết thêm các hàm tính toán khác và có thể chèn luôn vào công thức. (Trong ví dụ của tôi là hàm Test1)
Dạng câu lệnh truy vấn sẽ là
SELECT tbl_Sample.ID, tbl_Congthuc.CONGTHUC, ProcessFomula([Congthuc], tbl_Sample.HSLCU, tbl_Sample.HSLMOI, tbl_Sample.PCCU, tbl_Sample.PCMOI) AS Ketqua, tbl_Sample.HSLCU, tbl_Sample.HSLMOI, tbl_Sample.PCCU, tbl_Sample.PCMOI
FROM tbl_Sample INNER JOIN tbl_Congthuc ON tbl_Sample.MABIENDONG = tbl_Congthuc.MABIENDONG;
Và bây giờ bạn đã có thể làm thêm những gì mình cần.
Để có thêm thông tin, xin xem trong file đính kèm hoặc email cho tôi tại địa chỉ ngocdd@sfdp.net
Cảm ơn sự chú ý của các bạn.
File đính kèm xin tải về tại địa chỉ sau:
http://www.sfdp.net/Libs/gen/acc/Sample.rar

paulsteigel
18-08-2008, 16:20
Xin phép được post lại bài viết của tôi trong Webketoan.
[Nếu các bạn thấy việc này là không cần thiết - xin cho ý kiến nhé.]

Đầu bài là:


Giúp tạo macro in phiếu báo giá
Chào các bạn,bạn nào rành giúp mình tạo một macro trong file excel gửi kèm bên dưới với,mình muốn tạo một macro mà khi mình nhập in từ dòng nào đến dòng nào trong sheet Form2 thì macro nó sẽ chạy và điền dữ liệu tương ứng với từng khách hàng của từng dòng trong sheet DS vào cái form báo giá có sẵn cũng trong sheet Form2 luôn.Ví dụ in từ dòng 1 đến dòng 3 thì nó sẽ chạy ra 3 mấu báo giá trên cùng một sheet ( như mẫu trong sheet Form2 ),hoặc có thể in ra trên 3 sheet khác nhau cũng được.Mình gửi kèm file excel att dưới đây,bạn nào rành giúp mình cái nha,cám ơn nhiều.
P/s:Mình không gửi file excel Att được nên gửi qua link nha http://www.box.net/shared/sdfv81zbgu

Xin cám ơn nhiều

Xin chào các bạn,
Tiếp theo 2 ví dụ đã đăng trong bài trước, xin phép được giải thích một chút về cách tiếp cận trong các ví dụ mà mình đã đăng.
A. Mục đích:
Sử dụng Excel để in ra các dạng biểu mẫu cùng loại cho nhiều khách hàng khác nhau

B. Cấu trúc
Cả hai ví dụ đều có điểm chung là:
* Có bảng dữ liệu chứa dữ liệu khách hàng cần được in ra. Trong ví dụ về báo giá (Quotation) còn có thêm bảng dữ liệu về sản phẩm, áp dụng với trường hợp khách hàng cần được báo giá về nhiều loại sản phẩm.
* Có biểu mẫu đã được định dạng sẵn để in ra

C. Cách tiếp cận
Cả hai ví dụ đều có cách tiếp cận giống nhau đó là lấy dữ liệu từ các bảng cho trước, xử lý và đưa vào biểu mẫu sau đó cho phép người dùng có thể quy định vị trí, kiểu in, chèn thêm ngắt trang.
Tuy nhiên, có sự khác nhau khá lớn giữa mẫu in LableEx và mẫu báo giá. Trong báo giá, tôi sử dụng tham chiếu tên toàn cục và cục bộ để chuyển dữ liệu từ bảng gốc sang bảng đích. Trong khi đó tại ví dụ in nhãn trong Excel, tôi sử dụng tham chiếu tương đối có hiệu chỉnh dòng, cột theo yêu cầu đầu vào.

Về nguyên tắc, để làm được việc in ra các báo giá hoặc biểu mẫu với Excel chúng ta cần thỏa mãn được các vấn đề sau:
* Có bảng dữ liệu đầu vào được thiết kế chuẩn mực.
* Có bảng chứa biểu mẫu được đặt trong một trang tính khác có các cột dữ liệu để in nhất quán và được định dạng theo yêu cầu người dùng.
* Các thao tác chính sẽ được đặt trong một trang tính điều khiển để dễ quản lý.

Cách thực hiện về cơ bản như sau - xin trích dẫn mã nguồn trong ví dụ về Quotation:
1. Khởi tạo các biến số (tên vùng, bảng tính, trang tính)
* Thiết lập các vùng tham chiếu dữ liệu trong Form mẫu cho dễ tham chiếu (cách đặt tên đã được giới thiệu khá rõ trong các bài khác của diễn đàn)
Trong ví dụ này tôi thiết lập các vùng sau:

* Quotation: Chứa toàn bộ dữ liệu của mẫu
* rngCommodities: Chứa vùng dữ liệu về sản phẩm sẽ được in ra tại báo giá
* txtCustomerName: Chứa tên khách hàng
* txtCustomerAdd: Chứa địa chỉ khách hàng
* txtCustomerTel: Chứa số điện thoại của khách hàng
* txtOfferDate: Nơi sẽ in ra ngày hiệu lực điều chỉnh

Và các vùng tham chiếu đến dữ liệu cấu hình như:

* txtPrintFrom: Chỉ ra mẫu tin đầu tiên để in báo giá
* txtPrintTo: Chỉ ra mẫu tin cuối cùng để in báo giá
* txtIsNewPage: Có chèn thêm ngắt trang vào báo giá tiếp theo không (1 có, 2 không)
* txtRowSeparator: Số dòng phân cách giữa các báo giá

* Thiết lập biến số và tham chiếu trong thủ tục. Ở đây, thủ tục kích hoạt lệnh khởi tạo báo giá là PrepareQuotation:

Dim myWrkBook As Workbook ' Workbook hien thoi
Dim myDstWrkBook As Workbook ' Workbook cap copy den

' Khai bao Sheet tham so
Dim prmSheet As Worksheet ' Sheet chua du lieu tham so
Dim srcSheet As Worksheet ' Sheet chua du lieu khach hang
Dim refWrShet As Worksheet ' Sheet chua thong tin san pham
Dim dstRange As Range ' Vung chua du lieu can copy toi
Dim orgFormat As Range ' Vung chua form cua bieu mau
Dim i As Long

' Gan cac sheet nay voi sheet thuc te trong workbook
Set myWrkBook = ActiveWorkbook
Set prmSheet = myWrkBook.Sheets("ControlPanel")
Set srcSheet = myWrkBook.Sheets("S1")
Set refWrShet = myWrkBook.Sheets("Mathang")

' Khai bao cac bien so vung de truy cap
Dim RngData As Range ' Range chua data trong sheet khach hang

' Bay gio doc khoang cach can lam va in ra bao gia nhe...
' Khai bao bien so
Dim varPrintFrom As Long
Dim varPrintTo As Long
Dim varIsNewPage As Integer
Dim varRowSeparator As Integer

2. Đọc các dữ liệu cấu hình

' Lay cac gia tri dau vao
With prmSheet
varPrintFrom = .Range("txtPrintFrom")
varPrintTo = .Range("txtPrintTo")
varIsNewPage = .Range("txtIsNewPage")
varRowSeparator = .Range("txtRowSeparator")
End With

3. Tạo ra bảng tính chứa dữ liệu kết xuất cuối cùng.

' Chep form bao gia sang mot work book moi
Set myDstWrkBook = GetCopyForm(ActiveWorkbook.Sheets("Form"))

Đây là mã thủ tục

Private Function GetCopyForm(ObjToCopy As Worksheet) As Workbook
'
' Macro1 Macro
' Macro recorded 8/15/2008 by Paulsteigel
'
'
Dim objWrk As Workbook
Set objWrk = Workbooks.Add
ObjToCopy.Copy Before:=objWrk.Sheets(1)
Set GetCopyForm = objWrk
Set objWrk = Nothing
End Function

Tiếp theo,

' Tien hanh doc du lieu nhe
' rngHeader la vung chua Header cua Bang du lieu khach hang, thay vi phai dung cac diem bat dau

Set RngData = srcSheet.Range("rngHeader")
' ta se chi can dung thu tuc thi nhay ngay den dong chua du lieu dau tien
Set RngData = RngData.Offset(varPrintFrom)

' Gan Vung dich
Set dstRange = myDstWrkBook.Sheets("Form").Range("Quotation")
Set orgFormat = myWrkBook.Sheets("Form").Range("Quotation")

4. Duyệt qua vòng lặp để đọc các dữ liệu đầu vào và chép sang bảng dữ liệu kết xuất.

' Bay gio thuc hien vong lap de tien hanh copy du lieu nhe
For i = varPrintFrom To varPrintTo
TransferDataToForm RngData, dstRange, refWrShet
' Chuyen sang Vung tiep theo
Set RngData = RngData.Offset(1)

' Them dau ngan trang neu can thiet
If varIsNewPage = 1 Then
Set dstRange = dstRange.Offset(dstRange.Rows.Count + varRowSeparator + 1)
myDstWrkBook.Sheets("Form").HPageBreaks.Add dstRange.Offset(-1)
Else
Set dstRange = dstRange.Offset(dstRange.Rows.Count + varRowSeparator + 3)
End If
Set dstRange = dstRange.Offset(-1)
' Copy format tu bieu mau sang sheet moi
If i < varPrintTo Then
orgFormat.Copy
dstRange.PasteSpecial xlPasteAll
Application.CutCopyMode = False
End If
Next

5. Giải tỏa các biến đã tham chiếu khỏi bộ nhớ

' Giai toa cac bien so da khai bao va ket thuc
Set RngData = Nothing
Set prmSheet = Nothing
Set srcSheet = Nothing
Set myWrkBook = Nothing

6. Sơ lược về thủ tục chép dữ liệu sang biểu mẫu
Thủ tục TransferDataToForm RngData, dstRange, refWrShetđược sử dụng để sao chép từng bộ dữ liệu cho từng báo giá. Cách viết như sau:

Private Sub TransferDataToForm(srcRange As Range, destRange As Range, refSheet As Worksheet)
' Ham de copy du lieu sang form moi
Dim cmdCode As Variant ' Bien mang se giu ma hang hoa
Dim cmdCode_arr As String ' Bien giu chuoi ma hang hoa
Dim foundCell As Range ' Bien giu Vung co chua ma hang da tim thay
Dim searchRange As Range ' Bien giu Vung tim kiem ma hang
Dim copyRange As Range ' Bien giu Vung tim thay de copy vao vung dich
Dim destRow As Range ' Bien giu Vung chua 1 dong dau tien trong bao gia ve hang hoa
Dim i As Long

' Xac dinh vung tim ma hang nhe
Set searchRange = refSheet.Range("B:B")

' Truoc tien la copy cac gia tri dong quan trong nhu ten tuoi, dien thoai dia chi truoc
With destRange
.Range("txtCustomerName") = srcRange.Cells(1, 3)
.Range("txtOfferDate") = srcRange.Cells(1, 4)
.Range("txtCustomerTel") = srcRange.Cells(1, 5)
.Range("txtCustomerAdd") = srcRange.Cells(1, 6)
cmdCode_arr = srcRange.Cells(1, 7) ' Day la bang danh muc hang nhe
End With
' Bay gio den cot cac hang hoa se bao gom trong bao gia
' Trong co so du lieu toi co danh muc hang duoc ngan cach bang dau "/"
' PRO14/CON15/CON16/MEA17/SEA18/CON19/CON20
' An dinh vung copy moi
Set destRange = destRange.Range("rngCommodities")

' Tach cac ma hang ra thanh mang de de xu ly
cmdCode = Split(cmdCode_arr, "/")
' Duyet qua danh sach mat hang bang vong lap,
For i = 0 To UBound(cmdCode)
' UBound(cmdCode) la ham tra ve so thu tu cua phan tu cuoi cung trong mang, so phan
' tu thuc cua mang se la Ubound()+1
' Tim kiem ma hang nao
Set foundCell = searchRange.Find(cmdCode(i), , xlValues, xlWhole, xlByRows, xlNext, False)

' Bay gio tim den cac gia tri bo sung cua hang hoa can cu vao dong da nhan duoc nhe
' Ghi nho lai vung chua thong tin de sao sang form bao gia
Set copyRange = searchRange.Range(foundCell.Offset(0, -1), foundCell.Offset(0, 3))

' Chep vao bo nho
copyRange.Copy
' Dan sang dong dau tien cua bao gia
destRange.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
' Bo che do cat dan
Application.CutCopyMode = False

Set destRow = destRange.Offset(1, 0)
' Bo sung them mot dong nua nhe
If i < UBound(cmdCode) Then destRow.EntireRow.Insert
' Gan lai Vung vua them de cho vong lap sau
Set destRange = destRow.Offset(-1, 0)
Next

' Giai phong cac bien khoi bo nho
Set foundCell = Nothing
Set searchRange = Nothing
Set destRow = Nothing
Set copyRange = Nothing
End Sub

Trong mã tôi có chú thích khá nhiều về các biện pháp kỹ thuật, mã nguồn chi tiết đặt trong file đính kèm trong bài trước.
Trong các thủ tục ở đây, có vài điểm kỹ thuật cần lưu ý:
* Cách lưu trữ nhiều khóa vào một dùng và chuyển chúng thành mảng - học theo cách trỏ tham chiếu ngoài của Access. Các bạn có thể tạo ra hộp thoại để chọn danh sách các hàng hóa cho một báo giá với Listbox cho phép chế độ chọn MultipleSelection

' PRO14/CON15/CON16/MEA17/SEA18/CON19/CON20
' An dinh vung copy moi
Set destRange = destRange.Range("rngCommodities")

' Tach cac ma hang ra thanh mang de de xu ly
cmdCode = Split(cmdCode_arr, "/")

* Đoạn thủ tục sử dụng khả năng tìm kiếm trong Range của Excel một cách nhanh nhất mà không cần phải dùng cấu trúc lặp để duyệt qua các mẫu tin.

Set foundCell = searchRange.Find(cmdCode(i), , xlValues, xlWhole, xlByRows, xlNext, False)

* Đoạn thủ tục sử dụng tính năng sao chép và dán của Excel.

' Chep vao bo nho
copyRange.Copy
' Dan sang dong dau tien cua bao gia
destRange.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
' Bo che do cat dan
Application.CutCopyMode = False
Hy vọng các ví dụ này sẽ giúp ích phần nào cho các bạn quan tâm.

Có thể tải mã nguồn 2 ví dụ tại đây!
http://www.sfdp.net/Libs/gen/Exl/ExcelLabel.zip

paulsteigel
05-12-2008, 10:41
Tặng các bạn một Addin nho nhỏ dùng để chuyển đổi bảng mã văn bản dùng cho Excel.
Mình viết lại dựa trên bản dùng cho Word đã viết từ 2003.
Cách cài đặt cho Excel thì giống như Add in thông thường.
Cách dùng:
1. Chọn mã nguồn, đích bằng cách nhấn nút Select Code (Chỉ cần chọn 1 lần giống như Unikey, khi cần chuyển mã khác thì mới phải chọn lại)
2. Chọn vùng cần đổi mã và nhấn Alt+C hoặc Convert trên thanh công cụ.
Tiện thể mình cũng gửi bản cho Word để các bạn tham khảo.
- Hi hi xin góp vui cùng anh em.
Tiện thể, mình còn vài thứ chưa làm được vì bận quá đó là:
* Tự động đoán mã - cái này đoán dựa trên font chữ và kiểu ký tự nhận dạng - thiết kế thuật toán này thì cũng khá phức tạp nhưng rất tiện dụng.
* Tự động chuyển phông chữ hoa, thường - nói chung là dựa vào tên phông chữ và dùng các thuật toán của có trong giaiphapexcel.com của Đỗ Nguyên Bình và a Lê Văn Duyệt là ổn.
* Tối ưu hơn về tốc độ - về điểm này thì tớ chưa nghĩ ra giải pháp.
* Tự động cài vào Excel Add-in khi mở - cái này thì mình không muốn làm vì sợ các bạn bảo là Virus.
Nếu các bạn muốn thì cùng mình làm tiếp nhé.
Chúc các bạn vui vẻ.
Tải tập tin về tại:
Http://www.sfdp.net/Libs/gen/Exl/Functions.rar

huynbahuu
09-12-2008, 15:02
Cám ơn bạn đã có nhiều bài rất hay về chủ đề VBA trong Ofice.
Với bài "Tạo menu mới vào Excel" tôi đã thực hiện thử nhưng có một thắc mắc là có thể tạo thêm menu mới "Test" có menu cấp thấp hơn "Okay here is the test" thì có thể tạo thêm menu con cấp thấp hơn nữa mà tôi thấy trong Excel, có nghĩa là khi nhấn chuột vào menu "Okay here is the test" thì có thêm menu cấp thấp hơn được mở ra? (thường thấy xuất hiện hình tam giác trong menu đổ xuống). Ví dụ: Format\Row\Height...
Cho tôi hỏi thêm một ý nữa:
Nếu đã có một đoạn mã VBA như đoạn mã tạo menu của bạn thì sử dụng VB6 như thế nào để tạo được một file Setup mà khi người sử dụng cài đặt thì có ngay được menu trong Excel?
Cám ơn!

chooco_pie
09-12-2008, 19:09
thế còn tât cả các code trong access thì sao nè? mình đang tập làm một chương trình quản lý nhưng còn lủng củng về phần code..ai có thể cho mình tài liệu hay giào trình nào đọc nói về các code được không?

paulsteigel
09-12-2008, 19:57
Cám ơn bạn đã có nhiều bài rất hay về chủ đề VBA trong Ofice.
Với bài "Tạo menu mới vào Excel" tôi đã thực hiện thử nhưng có một thắc mắc là có thể tạo thêm menu mới "Test" có menu cấp thấp hơn "Okay here is the test" thì có thể tạo thêm menu con cấp thấp hơn nữa mà tôi thấy trong Excel, có nghĩa là khi nhấn chuột vào menu "Okay here is the test" thì có thêm menu cấp thấp hơn được mở ra? (thường thấy xuất hiện hình tam giác trong menu đổ xuống). Ví dụ: Format\Roe\Height...
Cho tôi hỏi thêm một ý nữa:
Nếu đã có một đoạn mã VBA như đoạn mã tạo menu của bạn thì sử dụng VB6 như thế nào để tạo được một file Setup mà khi người sử dụng cài đặt thì có ngay được menu trong Excel?
Cám ơn!

Cám ơn bạn đã hỏi, tôi xin trả lời từng ý như thế này
1. Về nguyên tắc có thể tạo vô hạn menu con của một menu miễn là bạn phải kiểm soát được ID hoặc index hoặc tag của menu vừa tạo để sử dụng nó và thêm các menu con.
Nhưng tại sao người ta không hay làm như thế?
+ Vì thường người dùng ngại việc phải truy cập quá sâu, nếu bạn phải đợi đến 5 lần bấm mới vô được tác vụ cần thiết thì kể cũng hơi ngại
+ Vì sẽ khó quản lý trong khi lập trình, tuy nhiên cũng không phải là quá khó, bạn có thể sử dụng các thuộc tính như tôi vừa nói và kết hợp với thủ thuật.
Chẳng hạn thuộc tính Tag cho phép bạn có thể đặt các dạng ký tự xác định để biết cấp menu - chẳng hạn mn1l2 thì tương đương với menu có ID1 trong cấp đó và thuộc cấp số 2....
Cách làm đó khá hữu dụng nếu bạn muốn bắt sự kiện và gắn tình trạng menu như một số bài tôi đã viết về quản trị cấp menu với các ứng dụng trong access
http://www.sfdp.net/Libs/gen/acc/mnbar.rar
2. Cũng vậy, về nguyên tắc bạn có tể sử dụng tập tin Setup.exe để tạo menu nhưng:
+ Bạn phải biết cách viết Script cho các trình tạo bộ cài đặt để tương tác với Excel OLE.
+ Hoặc bạn phải tự viết trình Setup.exe để làm điều đó.
Vậy có nên làm như vậy không? Câu trả lời là không nên vì quá mất thời gian và người ta có thể làm điều này một cách đơn giản là đặt tính năng tạo Menu trong chính ứng dụng Excel khi nó khởi động. Nhưng điều này cũng có một điểm bất lợi là nó phụ thuộc vào thiết lập an ninh của Excel.
(do ta phải bật macro của ứng dụng mà).
Lạm bàn như vậy, nếu bạn cần hỏi thêm, chúng ta cùng chia sẻ thêm nhé.
Kính thư

chooco_pie
09-12-2008, 21:10
hic sao hôk ai giúp hết ta... có tài liệu hay bài tham khảo gì cho mình biết về code trong access y. nè

huynbahuu
10-12-2008, 11:05
Cám ơn bạn đã hỏi, tôi xin trả lời từng ý như thế này
1. Về nguyên tắc có thể tạo vô hạn menu con của một menu miễn là bạn phải kiểm soát được ID hoặc index hoặc tag của menu vừa tạo để sử dụng nó và thêm các menu con.
Nhưng tại sao người ta không hay làm như thế?
+ Vì thường người dùng ngại việc phải truy cập quá sâu, nếu bạn phải đợi đến 5 lần bấm mới vô được tác vụ cần thiết thì kể cũng hơi ngại
+ Vì sẽ khó quản lý trong khi lập trình, tuy nhiên cũng không phải là quá khó, bạn có thể sử dụng các thuộc tính như tôi vừa nói và kết hợp với thủ thuật.
Cách làm đó khá hữu dụng nếu bạn muốn bắt sự kiện và gắn tình trạng menu như một số bài tôi đã viết về quản trị cấp menu với các ứng dụng trong access
2. Cũng vậy, về nguyên tắc bạn có tể sử dụng tập tin Setup.exe để tạo menu nhưng:
+ Bạn phải biết cách viết Script cho các trình tạo bộ cài đặt để tương tác với Excel OLE.
+ Hoặc bạn phải tự viết trình Setup.exe để làm điều đó.
Vậy có nên làm như vậy không? Câu trả lời là không nên vì quá mất thời gian và người ta có thể làm điều này một cách đơn giản là đặt tính năng tạo Menu trong chính ứng dụng Excel khi nó khởi động. Nhưng điều này cũng có một điểm bất lợi là nó phụ thuộc vào thiết lập an ninh của Excel.
(do ta phải bật macro của ứng dụng mà).
Kính thư
Rất cám ơn là bạn đã trả lời ngay (Tôi có hỏi một số diễn đàn khác như 0 có hồi âm).
Tôi đã xem phần ứng dụng trong access của bạn đã gửi. Nhưng chỉ thấy đến menu con và xuất hiện Form. Phần bạn giải thích về menu con cấp II trở đi thì tôi cũng hiểu được sơ lược về lý thuyết, nhưng cách làm cụ thể thì "Đang bó tay". Nếu có thời gian bạn viết cụ thể phần mã để tạo con menu đến cấp II để khi chạy trong Excel thì có ngay menu con cấp II. Tôi rất thắc mắc Microsoft viết như thế nào để được các menu như đã hỏi.
Việc thực hiện một tiện ích trong Office mà viết bằng Macro thì có khả năng sẽ bị một số phần mềm diệt Virus tiêu diệt nếu chọn diệt macro. Nên tôi muốn hỏi cụ thể là sau khi đã viết Macro rồi thì thực hiện tạo file Settup như thế nào để người sử dụng chỉ cần cài đặt là xong, không cần phải thao tác thủ công trong Office (Excel, Word, Access...). Vì cũng có rất nhiều người sử dụng không biết nhiều về các thao tác thủ công trong Office.
Rất mong bạn trả lời phương pháp thực hiện cụ thể hơn. Cám ơn!!!

paulsteigel
10-12-2008, 23:02
Mình hơi bận nên gửi bạn xem qua ví dụ này nhé, thay cho câu trả lời.
Bạn chỉ cần mở file Excel, thiết lập các đặc tính để kích hoạt Macro.

Option Explicit

Sub CreateMenu()
' Khai bao cac bien chua Command bar truoc
Dim myMnuBar As CommandBar
Dim MuMnuButton As CommandBarControl
Dim mnuTemp As CommandBarControl
Dim tblMenu As Range
Dim MnuType As MsoControlType

' Khai bao cac bien dem
Dim i As Long

' Bay gio doc du lieu tu vung dang chon voi cac header nhu sau cho de nho
' Menu ID Parrent ID Caption Action Tag
Set tblMenu = Selection

' 1. Khoi tao Thanh menu tam thoi, khi thoat excel thi het
If MenuBarExist("mnuBarTest") Then
'neu menubar nay da ton tai - xoa ngay
Application.CommandBars("mnuBarTest").Delete
End If

' Gio thi tao menu bar
Set myMnuBar = Application.CommandBars.Add("mnuBarTest", , , True)
' Hien thi no nao
myMnuBar.Visible = True
' Tao cac menu con
With myMnuBar
' Phai bat dau tu 2 vi ta co dong 1 la header
For i = 2 To tblMenu.Rows.Count
' Kiem tra truong ParentID
If tblMenu.Cells(i, 2) <> "" Then
' Day la menu con
' Tuy nhien phai kiem tra xem no se co the con co menu con nao nua khong nhe
' Sau do thi xac dinh kieu menu do
MnuType = GetMenuType(tblMenu, 2, tblMenu.Cells(i, 1).Value)
' vi mnu co cac mnu con nen phai gan cho no mot gia tri phu nhe
Set mnuTemp = CommandBars.FindControl(, , tblMenu.Cells(i, 2).Value)
If mnuTemp Is Nothing Then
' Khong tim thay menu do, chan qua - bo qua va bao loi
GoTo ExitSub
Else
Set MuMnuButton = mnuTemp.Controls.Add(MnuType, , , , True)
End If
Else
' Day la lop menu tren cung, khoi tao
Set MuMnuButton = .Controls.Add(msoControlPopup, , , , True)
End If
' Thiet lap Caption cho Menu
MuMnuButton.Caption = tblMenu.Cells(i, 3).Value
' Gio nho lai cai tag cua control nay nhe
MuMnuButton.Tag = tblMenu.Cells(i, 1).Value
Next
End With
ExitSub:
Set mnuTemp = Nothing
Set MuMnuButton = Nothing
Set myMnuBar = Nothing
End Sub

Private Function MenuBarExist(MenuBarName As String) As Boolean
Dim myMnuBar As CommandBar
Dim mnuCount As Long
On Error GoTo ErrHandler
Set myMnuBar = Application.CommandBars(MenuBarName)
mnuCount = myMnuBar.Controls.Count
MenuBarExist = True
ErrHandler:
End Function

Private Function GetMenuType(DataRange As Range, SearchColumn As Long, MenuTag As String) As MsoControlType
' Thu tuc nay xac dinh kieu menu bang cach tim xem co thay menu nao goi no bang cha khong
Dim SearchRange As Range
Set SearchRange = DataRange.Range(DataRange.Cells(2, SearchColumn), DataRange.Cells(DataRange.Rows.Count, SearchColumn))
If GetRangeValue(SearchRange.Find(MenuTag)) <> "" Then
' Kieu co the co menu con
GetMenuType = msoControlPopup
Else
' Kieu khong co menu con
GetMenuType = msoControlButton
End If
Set SearchRange = Nothing
End Function

Private Function GetRangeValue(MyRange As Variant) As String
' Ham nay de doi gia tri cua rang thanh dang text de ham thuc hien dung
On Error Resume Next
GetRangeValue = MyRange.Value
End Function

Tập tin kèm theo ở đây:
http://www.sfdp.net/my_softwares/excel_samples/t_o_menu_da_l_p/download.html
Hoặc ở đây nếu link trên bị chết
http://www.giaiphapexcel.com/forum/attachment.php?attachmentid=19283&d=1228924938
Còn việc tạo Setup thì bạn về VB6, tìm cái Setup1.vbp ở trong thư mục cài đặt của VB
C:\Program files\Microsoft Visual studio\VB98\Wizards\PDWizard\Setup1\SETUP1.VBP
Chắc bạn hiểu ý... bạn hoàn toàn có thể tùy biến nó để tự thêm menu vào excel khi cài đặt
Kính thư

huynbahuu
11-12-2008, 14:02
Cám ơn bạn rất nhiều, tôi chưa đọc hết nội dung nhưng làm thử thì về menu Toolbar đa lớp là tốt rồi. Đang thắc mắc ở mục tạo menu bar như đã hỏi là thực hiện thế nào để được menu bar, Ví dụ: Format\Row\Height...
Còn việc tạo file Setup từ VB6 khi đã có những macro như trên khi nào bạn có thời gian thì viết bài nhé!
Thank you very much indeed

paulsteigel
11-12-2008, 19:05
Hy vọng bài viết này sẽ giúp bạn nhé, cùng một nội dung đấy!
http://www.giaiphapexcel.com/forum/showthread.php?p=120514#post120514

huynbahuu
12-12-2008, 09:39
Hỏi bạn thêm một chút nhé! Tôi có tìm được một tài liệu về VBA ở dạng .chm
Nhưng khi mở ra thì bị báo lỗi không xem hình ảnh minh họa được. Nội dung ở hộp thoại Internet Explorer Scrit Error như sau:
An error has occurret in the script on thí page
Line: 17
Char: 1
Error: Not implemented
Code: o
URL: mk: ...vbad10.chm/links/woproDocumment1_l.htm
Do you want to continue running scrips on this page?
Không biết máy tính của tôi cài đặt thiếu phần nào mà không xem được hình hay là tại file bị lỗi?
Bạn có tài liệu nào về VBA cho tôi xin để nghiên cứu.
Bạn xem giúp file này ở đây:
http://s22.galaxyz.net/data/38010c080b000d/vbawd10.chm.glx
Cám ơn đã dành thời gian trả lời. Tôi đã xem nội dung của bạn trên diễn đàn giaiphapexcel. Bạn thật sự đã nghiên cứu rất sâu về VBA, thật khâm phục.

paulsteigel
12-12-2008, 09:57
Thực ra thì đó là lỗi thực thi của Scripts, bạn có thể tắt bỏ nó bằng chức năng cho phép thực hiện Script trong IE.
Hoặc bạn đi tìm một chương trình sửa CHM (link đây này http://www.chmeditor.com/?1332) và tìm file Script ofvbanli.js và comment dòng 15/ hoặc 16 gì đó liên quan đến hàm closeList.
Lưu lại file và chạy là xong
Nhưng tại sao phải làm vậy, bạn vô trang tải tài liệu của Microsoft hoặc lên google tìm "VBA reference" bạn sẽ có vô khối tài liệu.
nếu bạn đọc được tiếng Anh thì F1 và những sách như vậy là quá đủ để giỏi về VBA.
Thân!

huynbahuu
14-12-2008, 10:10
Cám ơn bạn! Tôi đã bỏ chức năng cho phép thực hiện Script trong IE và tạm thời xem tài liệu không có hình. Còn tiếng Anh thì tôi đọc được tuy đọc có mệt hơn đọc tài liệu tiếng Việt nhưng có hướng dẫn rất chi tiết và dễ hiểu.

[=========> Bổ sung bài viết <=========]

Làm thế nào để tạo một file chạy .exe như thế mày bạn? Phương pháp, phần mềm sử dụng? Có lẻ hơi khó!
Link:http://s21.galaxyz.net/data/231a1613111b12/Macros_2.exe.glx

changcodon777
14-12-2008, 21:44
Dim bm As Form
Dim list As Control
Dim multi As String
Dim hang As Variant
Set bm = Forms!form1
Set list = bm!SV

For Each hang In list.ItemsSelected
multi = multi & "'" & list.ItemData(hang) & "'" & ","
Next
multi = "MASV IN (" & multi & ")"

Dim rs As DAO.Recordset, rcsCount As Long
Set rs = CurrentDb.OpenRecordset("Select Count(*) as myCount from QUERYCHINH where " & multi & ";")
rcsCount = rs.Fields("myCount")
rs.Close
/////////////////////////////////
TÔI KHỘNG BIÊT NHƯNG CAU LỆNH O TREN AI BIẾT GIẢI THICH GIUM

huynbahuu
16-12-2008, 20:18
(VBA là cái mà tôi thích nhất)
Tôi cũng bước đầu thích VBA do đó trao đổi thêm với bạn. Trên diễn đàn giaiphapexcel bạn cho Link cũng có nhiều bài viết của bạn có giá trị.

paulsteigel
17-12-2008, 00:04
Cám ơn bạn! Tôi đã bỏ chức năng cho phép thực hiện Script trong IE và tạm thời xem tài liệu không có hình. Còn tiếng Anh thì tôi đọc được tuy đọc có mệt hơn đọc tài liệu tiếng Việt nhưng có hướng dẫn rất chi tiết và dễ hiểu.

[=========> Bổ sung bài viết <=========]

Làm thế nào để tạo một file chạy .exe như thế mày bạn? Phương pháp, phần mềm sử dụng? Có lẻ hơi khó!
Link:http://s21.galaxyz.net/data/231a1613111b12/Macros_2.exe.glx

Đó không phải là 1 file Exce, đơn giản là cách mà người thiết kế web diễn dịch các request web tại web server (giổng như http://www.***.yyy/index.php
hoặc .../index.tno
Nếu bạn muốn biết cái đó, bạn có thể lên đọc rewrite rule - không khó lắm đâu bạn ạ. Bạn có thể bắt đầu với Apache htpd server.
Chúc bạn vui vẻ!

[=========> Bổ sung bài viết <=========]


Dim bm As Form
Dim list As Control
Dim multi As String
Dim hang As Variant
Set bm = Forms!form1
Set list = bm!SV

For Each hang In list.ItemsSelected
multi = multi & "'" & list.ItemData(hang) & "'" & ","
Next
multi = "MASV IN (" & multi & ")"

Dim rs As DAO.Recordset, rcsCount As Long
Set rs = CurrentDb.OpenRecordset("Select Count(*) as myCount from QUERYCHINH where " & multi & ";")
rcsCount = rs.Fields("myCount")
rs.Close
/////////////////////////////////
TÔI KHỘNG BIÊT NHƯNG CAU LỆNH O TREN AI BIẾT GIẢI THICH GIUM


Bài này tôi đã trả lời tận tình cho các bạn qua email và yahoo rồi còn gì. Bạn nên đọc thêm một chút về DAO và cách xây dựng Query!

[=========> Bổ sung bài viết <=========]

Mình cũng vừa viết thêm một bài ngắn về thêm ảnh bên ngoài vào thực đơn của Office, đây là đường dẫn nhé!
http://www.giaiphapexcel.com/forum/showthread.php?t=17128
Còn bài này là cách sử dụng công cụ tra từ của Bamboo tra từ trong Word nhé
http://www.giaiphapexcel.com/forum/showthread.php?p=121697#post121697
Xin lỗi các bạn vì không gửi bài lại!

paulsteigel
23-12-2008, 18:01
Mình mạn phép không viết lại các bài đã đăng trên một diễn đàn khác nhưng xin được gửi tặng các bạn một số Addin dành cho Excel nhé:
1. Addin giup chuyển đổi bảng mã tiếng Việt trong Excel (đây là sản phẩm của nhiều tác giả)
http://www.giaiphapexcel.com/forum/showpost.php?p=123975&postcount=33
2. Addin giúp tra từ điển trên mạng ngay trong Word!
http://www.giaiphapexcel.com/forum/showthread.php?t=17304
Chúc các bạn vui vẻ!

duonglongvinh
13-05-2009, 17:46
Chao bac cho minh hoi ti nha!
Bac co cach nao export tu CSDL MySql ra excell theo dinh dang khong?
neu co xin duoc chi giao ha!
cam on hihi

paulsteigel
13-05-2009, 22:45
Đây là một trong số nhiều công cụ bạn ạ
http://downloadphanmem.com/Default.aspx/ProView1293/MySQL-to-Excel-25/

http://www.topshareware.com/MySQL-to-Excel-download-1423.htm

http://www.google.com.vn/search?hl=vi&client=firefox-a&rls=org.mozilla%3Aen-US%3Aofficial&hs=HxG&q=MySql+to+excell&btnG=T%C3%ACm+ki%E1%BA%BFm&meta=
Bạn chịu khó google một chút nhé!

duonglongvinh
16-05-2009, 16:41
cam on nhieu nha
hihi

[=========> Bổ sung bài viết <=========]

Cho minh hoi them ti nua ha minh moi lap trinh ha hihi
cach nao de tao uu tien khi minh goi form len bang VBA vay?
minh muon no o tren nhat tren cac form hihihi

thanks!!

paulsteigel
19-05-2009, 08:50
+ Chưa hiểu rõ ý bạn lắm, có thể là bạn muốn form được xuất hiện ở dạng modal
Bạn có thể đặt thuộc tính cho form là kiểu Dialog thì khi hiển thị, Access sẽ đợi hoàn thành công việc tại form đó nó mới cho quay lại form chính.
Hoặc có thể dùng lệnh form***.show vbmodal như trong VB

duonglongvinh
25-05-2009, 16:54
Thật cảm ơn khi được sự giúp đỡ của bạn!
cho minh hỏi tí nửa ha!hihi
có cách nào lấy được vị trí của form không bạn
nếu có xin giúp mình ha mình đang cần gấp
cảm ơn hihi!!

paulsteigel
29-05-2009, 08:49
Hiện tại, chưa có cách nào hữu hiệu để xác định vị trí form qua các sự kiện người dùng nên tôi phải dùng cách hơi củ chuối là đặt timer.
Cứ sau một thời gian nhất định (ở đây là 1 giây) thì sự kiện Form_Timer sẽ được kích hoạt và kiểm tra xem vị trí form có thay đổi không, nếu có thay đổi thì in ra vị trí mới qua các thuộc tính WindowLeft, top và thực hiện các thao tác khác nếu cần.
Bạn xem qua ví dụ dưới đây của tôi.

Option Compare Database
Dim theFormLeft As Long, theFormTop As Long

Private Sub Form_Open(Cancel As Integer)
Me.TimerInterval = 1000
End Sub

Private Sub Form_Timer()
If theFormLeft <> Me.WindowLeft Or theFormTop <> Me.WindowTop Then
Debug.Print Me.WindowLeft & "/Downd"
theFormLeft = Me.WindowLeft
theFormTop = Me.WindowTop
End If
End Sub

'================================================= ===
Hi vọng sẽ giúp được bạn phần nào.

duonglongvinh
04-06-2009, 20:25
Thật là cảm ơn bạn nhiều nha hihi!
Chúc bạn luôn thành công
byeeeeee.........
================================================== ==========
cuộc đời vẫn.....đẹp sao......tình iu vẩn đẹp sao............

skill_hva
10-06-2009, 17:08
Bài viết khá hay cám ơn U nhiều.

buon_vi_dep_2003
19-06-2009, 22:45
Chào bạn, mình muốn có 2 vấn đề không tìm cách giải quyết đựoc. Mong bạn chỉ hướng giải quyết

1. Trong Excel 2007, tôi thêm menu Developer, tôi thêm control MultiPagevào sheet1,
trên multipage tôi vẽ thêm 1 button, 1 textbox. Khi run chương trình, tôi gõ nội dung vào texbox, nhấp nút button thì tại dòng A1 hiện ra nội dung tôi đã ghi tại textbox


2.Trong Access, tôi có bảng dữ liệu sau

Masp | SoTien
100 | 150
101 | 50
102 | 30
----------------------
Tôi muốn thiết kế 01 query có data sau
Masp | SoTien | ST1
100 | 150 | 150
101 | 50 | 200
102 | 30 | 230
-----------------------------------




Mong bạn chỉ giúp!

ngochbvn
29-10-2009, 23:13
bạn ơi!giúp tôi với, tôi chưa biết nhiều về VBA, tôi đang phải làm bài tập quản lý trong access, có các nút thêm, sửa, xóa dữ liệu. Phải viết như thế nào. cảm ơn rất nhiều.

paulsteigel
27-12-2009, 19:10
Xin tặng các bạn yêu thích Excel bộ công cụ chuyển đổi bảng mã từ các bảng mã tiếng Việt (VNI/TCVN/Unicode/VIQR...) sang Unicode và ngược lại.
Liên kết chuyển đến trang diễn đàn khác:
http://www.sfdp.net/tai-lieu-khac/bocongcuchuyenma/Functions.rar
Để tải về được, các bạn cần đăng ký thành viên diễn đàn và truy nhập diễn đàn.
Xin chân thành cảm ơn và thành thực xin lỗi ban quản trị nếu có vấn đề gì về xung đột quan điểm.

P/S: Về câu hỏi của 2 bạn ngochbvb và buon_vi_dep_2003, nếu các bạn vẫn còn quan tâm đến câu trả lời (vì câu hỏi được đặt ra khá lâu rồi), xin đăng lại tin hoặc gửi email cho tôi tại ngocdd@sfdp.net nhé.

tieulongnu_young
18-08-2010, 14:47
Giúp viết macro để liên kết dữ liệu trong word[/B]
Xin chào cả nhà. Tôi là thành viên mới của diễn đàn và đang cần sự giúp đỡ của mọi người về VBA trong word.Hiện tại tôi có rất nhiều file cùng có một định dạng ở footer, file .doc. Ở phần footer này có một dòng chữ cần được thay đổi về nội dung bằng một câu khác. Vì có quá nhiều file và có thể nội dung này sau này sẽ thay đổi thêm lần nữa nên tôi không thể làm thủ công bằng cách copy và paste nội dụng được. Tôi có biết sơ về macro nhung không rành lắm. Vì vậy, tôi có ý tưởng thế này:
1. giả sử các file có footer cần thay đổi nội dung, tôi đặt tên là main1.doc
2. File chứa nội dung sẽ thay đổi, tôi đặt tên là source.doc
3. Việt một macro để tự động lấy nội dung bên file source.doc để chép vào các file main1.doc, main2.doc,...
4. Mục đích là nếu sau này thay đổi nội dung bên file source bằng một câu khác, tất cả các file main1.doc, main2.doc,...sẽ tự động update lại nội dung ở footer.

Các bạn vui lòng viết giùm tôi code cho yêu câu trên với nhé. Xin cám ơn các bạn nhiều.
Nick yahoo của tôi là tieulongnu_young. Nếu có gì khó hiểu thì có thể post message cho tôi qua yahoo, tôi sẽ trả lời liền.
Hy vọng được mọi người chia sẻ và trả lời.

tonybui2429
29-10-2010, 21:52
Xin chào mọi người, mình đang làm một macro VBA tạo form đề thi trắc nghiệm trên word. Mọi người có thể cho mình biết 1 vài cách hiệu quả nhất để giải quyết vấn đề này. Mong được sự giúp đỡ của các bạn.

chipsandcrisps
14-12-2010, 12:28
Mình có đoạn mã thế này mọi người giải thích giúp mình xem mỗi dòng lệnh có ý nghĩa như thế nào với. Cảm ơn nhìu!
Sub DiemToNhat()
Application.DisplayAlerts = False
Dim xMax As Object, xDiem As Object
Set xDiem = ThisWorkbook.Sheets("TieuHocK6")
xDiem.Copy After:=xDiem
a = 0
b = 0
Set xMax = ActiveSheet
R = 7
Do
For c = 6 To 62
If Cells(R, c) <> "" Then
vt = 1
diem = Cells(R, c) & ";"
vt1 = InStr(1, diem, ";")
If vt1 > 0 Then
diem1 = Val(Mid(diem, vt, vt1 - vt))
vt = vt1 + 1
Do
vt1 = InStr(vt, diem, ";")
a = 0
If vt1 > 0 Then
diem2 = Val(Mid(diem, vt, vt1 - vt))
vt = vt1 + 1
If diem1 < diem2 Then diem1 = diem2
Else
Cells(R, c) = diem1
Exit Do
End If
b = 0
a = 0
Loop
End If
End If
Next
R = R + 1
If Cells(R, 1) = "" Then Exit Do
Loop
Application.DisplayAlerts = True
End Sub

[=========> Bổ sung bài viết <=========]

Mình không biết nhiều, có thể nói không biết về VBA nhưng mình lại rất có nhu cầu dùng nó. Muốn học nhưng không biết bắt đầu từ đâu. Rất mong mọi người thương tình mà chỉ cho. Hic...

[=========> Bổ sung bài viết <=========]

Nếu có ai thương tình thì xin post câu trả lời trực tiếp lên diễn đàn hoặc nếu được thì mail giúp đến: chipsandcrisps@gmail.com. Cảm ơn nhiều.

paulsteigel
20-12-2010, 14:23
Option Explicit

Sub DiemToNhat()
' Day la thu tuc viet trong Excel VBA
' Muc dich: Tim ra diem lon nhat trong day cac diem duoc phan cach voi nhau bang
' dau ";" trong 1 o sau do gan gia tri o do bang diem lon nhat nay.
' Neu O do khong co du lieu thi bo qua
' Thu tuc xet du lieu tai dong 7 tro di va dung lai khi du lieu tai o ung voi dong dang xet va cot 1 khong co du lieu

' Tat canh bao cua he thong
Application.DisplayAlerts = False
' Khai bao khoi tao cac bien doi tuong dang Range de tham chieu den Sheet nao do cua Excel
Dim xMax As Object, xDiem As Object, a As Long, b As Long, R As Long, c As Long
Dim vt As Long, vt1 As Long, Diem As String, Diem1 As Long, Diem2 As Long
' Gan xDiem voi Sheet co ten la "TieuHocK6"
Set xDiem = ThisWorkbook.Sheets("TieuHocK6")
' Chep sheet "TieuHocK6" ra mot sheet moi dung sau Sheet nay
xDiem.Copy After:=xDiem
' Gan 2 bien dem bang 0
a = 0
b = 0
' Gan xMax cho Sheet hien thoi dang duoc kich hoat trong bang tinh
Set xMax = ActiveSheet
' Gan bien R voi gia tri bat dau la 7 (day la bien chay so dong, rat co the trong sheet hien tai, dong
' can xu ly du lieu la dong 7 tro di
R = 7
' Bat dau vong lap
Do
For c = 6 To 62
' Xet dieu kien voi gia tri cua mot o tai dong R, cot c xem co rong (empty) khong
If Cells(R, c) <> "" Then
' Neu co du lieu
vt = 1
' Gan bien diem voi gia tri cua o dang xet
Diem = Cells(R, c) & ";"
' Gan bien vt1 voi vi tri xuat hien ky tu ";" trong chuoi diem
' ham InStr() de xac dinh vi tri xuat hien mot ky tu nao do trong chuoi cho truoc
vt1 = InStr(1, Diem, ";")
If vt1 > 0 Then
' Neu vt1 >0 tuc la co ky tu ";" trong chuoi
' dung ham Val de chuyen chuoi so diem trong chuoi diem sang dang so va gan cho bien diem1
Diem1 = Val(Mid(Diem, vt, vt1 - vt))
vt = vt1 + 1
' Bat dau vong lap thu 2 de tach lay diem thu 2 xuat hien sau ky tu ";" va so sanh
' neu diem thu 2 lon hon diem truoc thi gan diem lon hon bang diem2 roi xu ly cho den
' het. Khi khong con dau ";" ke tu vi tri "vt" thi thoat khoi vong lap bang
' lenh Exit Do va lam tiep cho cac Cell khac.
Do
vt1 = InStr(vt, Diem, ";")
a = 0
If vt1 > 0 Then
Diem2 = Val(Mid(Diem, vt, vt1 - vt))
vt = vt1 + 1
If Diem1 < Diem2 Then Diem1 = Diem2
Else
Cells(R, c) = Diem1
Exit Do
End If
b = 0
a = 0
Loop
End If
End If
Next
R = R + 1
' Thoat ra neu dong ke tiep co cot 1 bo trong
If Cells(R, 1) = "" Then Exit Do
Loop
' Bat lai canh bao cua he thong
Application.DisplayAlerts = True
End Sub

' Thu tuc tren nhin chung la phuc tap, ta co the co cac lam khac nhanh hon nho viec su dung ham Split de lam viec voi mang
' Ngoai ra, ta co the viet thanh dang ham de co the su dung nhu dang cong thuc nguoi dung.
' Chang han tai mo o tuong uong co the viet dang =DiemToNhatX(Ten O chua chuoi diem)
Function DiemToNhatX(Target As Range) As Single
' Tat canh bao cua he thong
Application.DisplayAlerts = False
' Khai bao khoi tao cac bien doi tuong dang Range de tham chieu den Sheet nao do cua Excel
Dim xString As String ' Bien chua chuoi can xet
Dim xArr As Variant ' Bien chua mang ky tu
Dim xMaxVal As Single ' Bien chua gia tri lon nhat
Dim i As Long ' bien dem cua vong lap
xMaxVal = 0
xString = Target.Value
' Neu chuoi nay khong co gia tri thi di den dong lenh ExitFunction
If xString = "" Then GoTo ExitFunction
' Tach chuoi xString thanh mang voi dau phan cach cac phan tu mang la ";"
xArr = Split(xString, ";")
For i = LBound(xArr) To UBound(xArr)
If Val(xArr(i)) > xMaxVal Then
xMaxVal = Val(xArr(i))
End If
Next
ExitFunction:
If xMaxVal = 0 Then
DiemToNhatX = ""
Else
DiemToNhatX = xMaxVal
End If
' Bat lai canh bao cua he thong
Application.DisplayAlerts = True
End Function

langtua7
28-02-2011, 15:51
Cảm ơn các anh vì đề tài rất hay này ! Thấy các anh rất Pro về Excel nên em muốn hỏi xem mấy anh có biết cách nào chuyển file *.csv sáng file excel *.xls được không ạ !
Và cách Macro update vào excel thì sao ạ !
Em chân thành cảm ơn và rất vui khi được trả lời ạ !
Thân chào !

dragonnuce
07-03-2011, 01:10
Nghe các anh chị nói về VBA rất hay và em cũng nghe nói về nó là rất hữu ích nhưng xem các bài viết của các anh chị em vẩn chưa hiểu gì cả
Các anh chị có thể nói cho em hiểu 1 cách cơ bản về nó được không
nếu có giáo trình thì càng tốt ạ
Cảm ơn các anh chị nhiều ạ.

duongnvm
08-07-2011, 09:37
Chuyêm mục này quá hay!

cn05057
14-08-2011, 21:09
Bạn ơi cho mình hỏi, mình có tạo một form nhâp liệu trong excel dùng VBA. Nhưng mình ko biết cách dùng. Mình muốn ra record macro nhung ko làm sao mà chạy được form cần nhập liệu lên, mong các bạn chung tay giúp đỡ. cám ơn nhiều