Chuyên đề giải đáp những thắc mắc về code VBA

Liên hệ QC

maytinhvp01

Thành viên thường trực
Tham gia
27/7/13
Bài viết
390
Được thích
179
Mình muốn nhờ giải thich câu lệnh " If Ran.Cells(d, c) > max Then max = Ran.Cells(d, c) "
trong ví du:
Public Function LonNhat(Ran As Range)
Dim max As Double, v As Integer, d As Integer, c As Integer
max = Ran.Cells(1, 1)
For d = 1 To Ran.Rows.Count
For c = 1 To Ran.Columns.Count
If Ran.Cells(d, c) > max Then max = Ran.Cells(d, c)
Next c
Next d
v = Tim(max, Ran)
LonNhat = max
End Function
-------------------------------------------------------
[INFO1]Thông báo:
Vì topic này:
http://www.giaiphapexcel.com/forum/...ải-thích-các-code-đề-nghị-các-bạn-gửi-vào-đây
đã quá dài nên BQT đóng lại.
Nay tôi mở topic mới với cùng chủ đề: GIẢI THÍCH NHỮNG THẮC MẮC VỀ CODE
Các bạn nếu có nhu cầu giải thích code, vui lòng post tại đây nhé
NDU96081631

[/INFO1]
 
Chỉnh sửa lần cuối bởi điều hành viên:
Cảm ơn mọi người OT đã xử lý được rồi ạ, mặc dù nó hơi dài ạ:

Dùng câu lệnh "INSERT INTO..." nó còn liên quan đến kiểu dữ liệu được qui định của từng cột trong Table nữa nhé. Ví dụ: kiểu Text phải để trong dấu ngoặc đơn, kiểu số không cần, kiểu Date thì dấu #..# (cho table Access)... Chú ý vụ này.
 
Upvote 0
PHP:
Option Explicit

Sub Test()
    Const prefix = "INSERT INTO TABLE_NAME  ("
    Dim sh As Worksheet, arr As Variant, s As String
    Dim i As Long, ub As Long
    Set sh = ThisWorkbook.Worksheets("DL")
    Dim dong1 As String, res As Variant
    
    arr = sh.Range("D1").Resize(6, 5).Value2
    'dong 1
    dong1 = join_by_row(arr, 1) & ") VALUES "
    ub = UBound(arr, 1)
    ReDim res(2 To ub)
    'khuc duoi
    For i = 2 To UBound(arr, 1)
        res(i) = "(" & join_by_row(arr, i) & ")"
    Next i
    s = prefix & dong1 & Join(res, ",")
    MsgBox s
End Sub

Private Function join_by_row(ByVal data_ As Variant, ByVal irow_ As Long, _
                             Optional ByVal sdeli As String = ",")
    'noi cac phan tu cua data_ trong dong irow_, boi dau phay
    'data_: mang du lieu
    'irow_: dong can xet
    Dim ub As Long, i As Long, res As Variant
    ub = UBound(data_, 2)
    ReDim res(1 To ub)
    For i = 1 To ub
        res(i) = data_(irow_, i)
    Next i
    join_by_row = Join(res, sdeli)
    Erase res
End Function
 
Upvote 0
Dùng câu lệnh "INSERT INTO..." nó còn liên quan đến kiểu dữ liệu được qui định của từng cột trong Table nữa nhé. Ví dụ: kiểu Text phải để trong dấu ngoặc đơn, kiểu số không cần, kiểu Date thì dấu #..# (cho table Access)... Chú ý vụ này.
Xin chào anh ongke0711,
Cảm ơn Anh đã chỉ dẫn ạ ,
OT đã hiểu thêm được một chút về CSDL nghĩa là trước khi ghi dữ liệu vào thì cần phải kiểm tra data_type của từng trường sau đó sẽ gán giá trị tùy thuộc và từng kiểu trường đó ạ.

PHP:
Option Explicit

Sub Test()
    Const prefix = "INSERT INTO TABLE_NAME  ("
    Dim sh As Worksheet, arr As Variant, s As String
    Dim i As Long, ub As Long
    Set sh = ThisWorkbook.Worksheets("DL")
    Dim dong1 As String, res As Variant
   
    arr = sh.Range("D1").Resize(6, 5).Value2
    'dong 1
    dong1 = join_by_row(arr, 1) & ") VALUES "
    ub = UBound(arr, 1)
    ReDim res(2 To ub)
    'khuc duoi
    For i = 2 To UBound(arr, 1)
        res(i) = "(" & join_by_row(arr, i) & ")"
    Next i
    s = prefix & dong1 & Join(res, ",")
    MsgBox s
End Sub

Private Function join_by_row(ByVal data_ As Variant, ByVal irow_ As Long, _
                             Optional ByVal sdeli As String = ",")
    'noi cac phan tu cua data_ trong dong irow_, boi dau phay
    'data_: mang du lieu
    'irow_: dong can xet
    Dim ub As Long, i As Long, res As Variant
    ub = UBound(data_, 2)
    ReDim res(1 To ub)
    For i = 1 To ub
        res(i) = data_(irow_, i)
    Next i
    join_by_row = Join(res, sdeli)
    Erase res
End Function

Xin chào befaint,
Cảm ơn Bạn rất nhiều.
-------
Chúc mọi người vui khỏe.
OT
Bài đã được tự động gộp:

Dùng câu lệnh "INSERT INTO..." nó còn liên quan đến kiểu dữ liệu được qui định của từng cột trong Table nữa nhé. Ví dụ: kiểu Text phải để trong dấu ngoặc đơn, kiểu số không cần, kiểu Date thì dấu #..# (cho table Access)... Chú ý vụ này.

Xin chào Anh ongke0711,
Nhờ anh chỉ dâ thêm có phải SQL chỉ cho phép "INSERT INTO ..." 1000 dòng 1 lúc được thôi phải không phải không ạ?
OT thử thì vượt quá hệ thống không cho phép báo lỗi, và xóa <=1000 thì OK ạ.
Cảm ơn Anh ạ.
 
Lần chỉnh sửa cuối:
Upvote 0
Nhờ anh chỉ dâ thêm có phải SQL chỉ cho phép "INSERT INTO ..." 1000 dòng 1 lúc được thôi phải không phải không ạ?
OT thử thì vượt quá hệ thống không cho phép báo lỗi, và xóa <=1000 thì OK ạ.

Theo code trên thì em đang dùng kiểu Insert mới có từ SQL Sv 2008 trở lên: dùng Table Value và cách này bị giới hạn 1.000 dòng là đúng rồi.
Anh chưa dùng cách này nhưng em biến tấu nó chút:

Mã:
INSERT INTO TABLE_NAME (Col1,Col2,Col3,Col4,Col5)
SELECT Col1_data1,Col2_data1,Col3_data1,Col4_data1,Col5_data1
UNION ALL SELECT Col1_data2,Col2_data2,Col3_data2,Col4_data2,Col5_data2
UNION ALL SELECT Col1_data3,Col2_data3,Col3_data3,Col4_data3,Col5_data3
...

Hoặc:

Mã:
INSERT INTO TABLE_NAME (Col1,Col2,Col3,Col4,Col5)
SELECT * FROM (VALUES
(Col1_data1,Col2_data1,Col3_data1,Col4_data1,Col5_data1),
(Col1_data2,Col2_data2,Col3_data2,Col4_data2,Col5_data2),
(Col1_data3,Col2_data3,Col3_data3,Col4_data3,Col5_data3),
(..),
...
) AS TEMP (Col1,Col2,Col3,Col4,Col5);
 
Upvote 0
Em mới vào nghề đang học cơ bản về VBA
Có đoạn video dạy trên mạng. Em gõ code theo để chạy thử.
Nhưng code báo lỗi khi khai báo function.
Nhờ mọi người chỉ dạy hộ em, code bị sai chỗ nào
 

File đính kèm

Upvote 0
Em mới vào nghề đang học cơ bản về VBA
Có đoạn video dạy trên mạng. Em gõ code theo để chạy thử.
Nhưng code báo lỗi khi khai báo function.
Nhờ mọi người chỉ dạy hộ em, code bị sai chỗ nào
Theo mình thấy code bạn bị sai cú pháp, bạn chỉnh thử ở đoạn này
Mã:
demchuoiso = "co " & k & " so va co " & l & " chuoi "
 

File đính kèm

Upvote 0
Mình mới học VBA. Các bạn giải thích giúp mình đoạn Code sau sai ở đâu ?
Mã:
Public sh As String
Sub bieuTK1()
ThisWorkbook.Worksheets.Add after:=Sheets(Sheets.Count)
 Sheets(Sheets.Count).Name = "B1"
 'ThisWorkbook.VBProject.VBComponents(ThisWorkbook.Worksheets("B1").CodeName).Name = "TK1"
Set sh1 = Sheets("B1").CodeName
sh1.Range("A2").Select
End Sub

Toàn báo lỗi ở đoạn này Set sh1 = Sheets("B1").CodeName mà mình khhông hiểu tại sao ?
 
Upvote 0
Mình mới học VBA. Các bạn giải thích giúp mình đoạn Code sau sai ở đâu ?
Mã:
Public sh As String
Sub bieuTK1()
ThisWorkbook.Worksheets.Add after:=Sheets(Sheets.Count)
Sheets(Sheets.Count).Name = "B1"
'ThisWorkbook.VBProject.VBComponents(ThisWorkbook.Worksheets("B1").CodeName).Name = "TK1"
Set sh1 = Sheets("B1").CodeName
sh1.Range("A2").Select
End Sub
Toàn báo lỗi ở đoạn này Set sh1 = Sheets("B1").CodeName mà mình khhông hiểu tại sao ?
Sh1 là tham biến & tệ là bạn chưa khai báo kiểu dữ liệu cho nó; Nhưng bạn buộc máy phải hiểu đó là biến đối tượng.
Vậy bạn xem vế thứ 2 của biểu thức 'gán' đó có kiểu dữ liệu là gì chưa?
 
Upvote 0
Sheets("B1").CodeName là 1 giá trị chuỗi (code name của 1 sheet). Set dùng để gán giá trị đối tượng cho 1 biến. Thế là lỗi Type MisMatch
 
Upvote 0
Mình phải sửa như nào, Sheet(“B1”).CodeName mình vẫn phải khai biến sao. Biến sh1 mình đã khai báo là Public as string không đúng sao bạn. Mình phải sửa thế nào mong các anh chị thầy cô diễn đàn sửa giúp
 
Upvote 0
Khai báo As String là kiểu chuỗi, không gán đối tượng worksheet được.
Khai báo worksheet thì được, nhưng không gán chuỗi vào được
Với code bài 1 thì chỉ cần bỏ .CodeName ra:

Mã:
Set sh1 = Sheets("B1")
 
Upvote 0
Set là lệnh gán địa chỉ của đối tượng cho một biến đối tượng.
(nếu bạn không hiểu câu trên thì nên chịu khó bỏ thời giờ học về biến, kiểu biến, đối tượng và lệnh let/set)

Trong code của bạn, cần sửa:
Set sh1 = Sheets("B1").CodeName
sh1.Range("A2").Select
thành:
sh1 = Sheets("B1").CodeName ' sh1 bây giờ là kiểu chuỗi chứ không phải kiểu đối tượng
For Each sh In Sheets
If sh.CodeName = sh1 Then sh.Range("A2").Select ' sh1 là khoá để lọc ra cái sheet có tên CodeName
Next Sh

Chú:
VBA có hai hạng biến (ở đây nói hạng chứ không phải loại): hạng đơn giản và hạng phức tạp.
Lệnh gán trong VBA chia ra thành Let cho hạng đơn giản và Set cho hạng phức tạp.
Về sau này, VBA tự đơn giản bằng cách hiểu ngầm "Let". Vì vậy, lệnh gán hạng đơn giản khogn cần phải có từ khoá Let
Let A = B bây giờ viết là A = B (giá trị của B được cóp qua A)
Tuy nhiên, lệnh gán hạng phức tạp vẫn không được đơn giản hoá. Vẫn phải dùng Set.
Lênh Set có nghĩa là cóp địa chỉ của đối tượng, không phải trị của đối tượng.
Set A = B có nghĩa là A và B sẽ cùng chỉ vào chung một đối tượng.
 
Lần chỉnh sửa cuối:
Upvote 0
Anh/chị có thể viết cho em 1 module insert thêm dòng từ sheet dữ liệu ban đầu sau khi chạy thì ra kết quả như sheet kết quả mong muốn của em không ạ. Em cảm ơn rất nhiều.
 

File đính kèm

Upvote 0
Mình có file code VBA như file đính kèm.
Mục đích file này, giúp công nhân giảm thiểu thời gian gõ bàn phím (ví dụ : trong file đã thiết lập nút bấm KEYSET, để công nhân nhập 53.8 vào excel, thay vì phải gõ 53.8, chỉ cần gõ 7 là tự động nhập 53.8 vào cell).

Tuy nhiên, mình đang mới học cơ bản về VBA. Mình vẫn chưa hiểu được thuật toán trong code. Nhờ các bác chỉ dạy giúp em các điểm dưới đây :
1. Sub TIMDEY() có tác dụng gì
2. Userform Macro1 (nút bấm START). Trong code UserForm1.Show, theo em hiểu khi ấn START, thì nó sẽ hiện userform1 lên thôi. Tại sao, ấn nút START này, nó lại liên kết chạy được cả code Sub WR(). Từ đó dẫn đến mình có thể thao tác gõ phím tắt thông qua Keyset
3. Code Sheet2.Cells(J, I).Value = KEYDAT(KEYINDX)
Em tìm trên mạng, hay thư viện đều không tìm thấy hướng dẫn về KEYDAT. Các bác chỉ em cách dùng KEYDAT, hoặc link có nói về nó. Trong code của file, cũng không thấy có code nào liên kết với keyset. Tại sao KEYSET lại hoạt động được.

Sorry bài viết em có gì khó hiểu mong các bác phản hồi.

Thanks
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
1. Tìm hiểu về DoEvents => chủ yếu của cái sub đó.
2. Khi UserForm1.Show thì nó gọi tiếp KEYDAT(I) => bấm chuột phải lên form =>view code
3. KEYDAT (I) => người ta định nghĩa ngay đầu module đấy, tìm trên mạng sa ra được.
 
Upvote 0

File đính kèm

Upvote 0
Các bạn cho hỏi code dưới có thể rút gọn được không?
PHP:
Sub ThayThe()
    Selection.Replace What:="x", Replacement:="a", LookAt:=xlWhole, _
        SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
        ReplaceFormat:=False
    Selection.Replace What:="x.1", Replacement:="a", LookAt:=xlWhole, _
        SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
        ReplaceFormat:=False
    Selection.Replace What:="n", Replacement:="a", LookAt:=xlWhole, _
        SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
        ReplaceFormat:=False
End Sub
xin cảm ơn!
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom