Đố vui về VBA! (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

anhtuan1066

Thành viên gạo cội
Tham gia
10/3/07
Bài viết
5,802
Được thích
6,912
Nhằm cũng cố kiến thức về VBA cho các bạn mới bắt đầu và cả những bạn đang ứng dụng mà chưa hiểu nhiều về nó, tôi mở topic này với mong mõi qua những câu hỏi vui, các bạn sẽ nhận định lại sự hiểu biết cũa mình... (Kễ cã chính tôi cũng đang tập tành nên có rất nhiều cái chưa biết)
Mong rằng topic sẽ mang đến cho các bạn những khám phá thú vị với những cái tưỡng chừng như đã biết
Mong nhận dc bài viết về câu đố cũa các cao thủ! Còn các bạn mới thì đừng ngại khi đưa ra ý kiến cũa mình.. Có sai có sữa sẽ hoàn thiện!
Tôi xin mỡ màn trước bằng 1 câu hỏi đơn giãn
ANH TUẤN

CÂU HỎI 1: Tại sao biến K ko hoạt động?
Tôi muốn khi nhấn vào 1 button thì cell A1 sẽ tăng lên 1 đơn vị... Tôi đã làm như sau:
-Tạo 1 Command Button (nút nhấn thuộc thanh Control Toolbox), click phải chuột lên nút nhấn, chọn View code, rồi gõ vào đoạn code sau:
PHP:
Private Sub CommandButton1_Click()
   K = K + 1
   Range("A1").Value = K
End Sub
Ban đầu K chưa có gì, xem như =0, nhấn nút lần thứ nhất thì K dc tăng thêm 1, vậy K hiện tại sẽ bằng 1, và gán K vào cell A1 thì đương nhiên A1 sẽ =1... Nhấn nút lần 2, K lại dc tăng thêm 1 nên hiện tại K sẽ =2 và cell A1 cũng sẽ =2... vân vân.. từ đó diễn tiến tiếp...
Hi.. hi.. Điều này nghe qua có vẽ rất hợp lý, ấy thế mà khi nhấn nút nó chỉ hoạt động dc duy nhất 1 lần (A1 = 1) rồi thôi ko nhút nhít nữa...
Các bạn có thể giãi thích tại sao lại như thế ko? Tại sao những lần nhấn nút sau đó K lại ko tăng thêm tí nào (vì thực tế A1 vẫn cứ = 1 hoài) ?
ANH TUẤN
 
Trong khi chờ đợi câu trả lời của bài gán text cho label, mình xin "câu khách" một câu đố đơn giản!

Mình có một chuỗi bất kỳ, muốn loại bỏ 5 ký tự đầu, dùng HÀM gì trong VBA để cắt bỏ 5 ký tự đó mà CHỈ DÙNG ĐÚNG 1 HÀM

VD như vầy là dùng 2 hàm: MID(txt, 5, LEN(txt)) thì xem như giải không đúng yêu cầu!
 
Upvote 0
Trong khi chờ đợi câu trả lời của bài gán text cho label, mình xin "câu khách" một câu đố đơn giản!

Mình có một chuỗi bất kỳ, muốn loại bỏ 5 ký tự đầu, dùng HÀM gì trong VBA để cắt bỏ 5 ký tự đó mà CHỈ DÙNG ĐÚNG 1 HÀM

VD như vầy là dùng 2 hàm: MID(txt, 5, LEN(txt)) thì xem như giải không đúng yêu cầu!
Em thay cái hàm LEN đó thành 1 con số thiệt là bự có được không anh Nghĩa?
 
Upvote 0
Trong khi chờ đợi câu trả lời của bài gán text cho label, mình xin "câu khách" một câu đố đơn giản!

Mình có một chuỗi bất kỳ, muốn loại bỏ 5 ký tự đầu, dùng HÀM gì trong VBA để cắt bỏ 5 ký tự đó mà CHỈ DÙNG ĐÚNG 1 HÀM

VD như vầy là dùng 2 hàm: MID(txt, 5, LEN(txt)) thì xem như giải không đúng yêu cầu!

Vầy chắc được:
Mã:
Sub Test()
  Dim txt As String
  txt = "Hoang Trong Nghia"
  MsgBox Mid(txt, 5)
End Sub
 
Upvote 0
Trong khi chờ đợi câu trả lời của bài gán text cho label, mình xin "câu khách" một câu đố đơn giản!

Mình có một chuỗi bất kỳ, muốn loại bỏ 5 ký tự đầu, dùng HÀM gì trong VBA để cắt bỏ 5 ký tự đó mà CHỈ DÙNG ĐÚNG 1 HÀM

VD như vầy là dùng 2 hàm: MID(txt, 5, LEN(txt)) thì xem như giải không đúng yêu cầu!
Thử vầy coi sao. Chỉ 1 mà thôi đấy
PHP:
Sub test()
Dim chuoi
chuoi = 123456789
MsgBox Replace(chuoi, "", "", 6)
End Sub
 
Upvote 0
Thử vầy coi sao. Chỉ 1 mà thôi đấy
PHP:
Sub test()
Dim chuoi
chuoi = 123456789
MsgBox Replace(chuoi, "", "", 6)
End Sub

OK, cuối cùng quanghai đúng với đáp án của mình!

Mình đã thử các trường hợp, nhưng thời gian ngang ngang nhau, các bạn thử với mình xem cái nào là nhanh nhất, các bạn thử dữ liệu với cả cột thử xem sao!

Mã:
Sub test1()
    Dim Arr, i As Long, t As Double
    t = Timer
    [C:C].Clear
    Arr = [A:A]
    For i = 1 To 65536
        Arr(i, 1) = Right(Arr(i, 1), Len(Arr(i, 1)) - 36)
    Next
    [C:C] = Arr
    MsgBox Timer - t
End Sub

Sub test2()
    Dim Arr, i As Long, t As Double
    t = Timer
    [D:D].Clear
    Arr = [A:A]
    For i = 1 To 65536
        Arr(i, 1) = Replace(Arr(i, 1), "", "", 37)
    Next
    [D:D] = Arr
    MsgBox Timer - t
End Sub

Sub test3()
    Dim Arr, i As Long, t As Double
    t = Timer
    [E:E].Clear
    Arr = [A:A]
    For i = 1 To 65536
        Arr(i, 1) = Mid(Arr(i, 1), 37)
    Next
    [E:E] = Arr
    MsgBox Timer - t
End Sub
 
Upvote 0
OK, cuối cùng quanghai đúng với đáp án của mình!

Mình đã thử các trường hợp, nhưng thời gian ngang ngang nhau, các bạn thử với mình xem cái nào là nhanh nhất, các bạn thử dữ liệu với cả cột thử xem sao!

Bậy không!
Test vậy sao công bằng với hàm RIGHT (vì bắt nó tính toán 2 lần)
Phải vầy mới đúng:
Mã:
Sub test1()
  Dim Arr, i As Long, t As Double, tmp As String
  t = Timer
  [C:C].Clear
  Arr = [A:A]
  For i = 1 To 60000
    tmp = Arr(i, 1)
    Arr(i, 1) = Right(tmp, Len(tmp) - 36)
  Next
  [C:C] = Arr
  MsgBox Timer - t
End Sub
Mã:
Sub test2()
  Dim Arr, i As Long, t As Double, tmp As String
  t = Timer
  [D:D].Clear
  Arr = [A:A]
  For i = 1 To 60000
    tmp = Arr(i, 1)
    Arr(i, 1) = Replace(tmp, "", "", 37)
  Next
  [D:D] = Arr
  MsgBox Timer - t
End Sub
Mã:
Sub test3()
  Dim Arr, i As Long, t As Double, tmp As String
  t = Timer
  [E:E].Clear
  Arr = [A:A]
  For i = 1 To 60000
    tmp = Arr(i, 1)
    Arr(i, 1) = Mid(tmp, 37)
  Next
  [E:E] = Arr
  MsgBox Timer - t
End Sub
Test xong, 3 code cho kết quả gần như nhau (trên máy tôi là 1.2s)
 
Upvote 0
Nghe qua thì rất có lý, nhưng nên biết rằng topic này là BÀN VỀ VBA, tức là VIẾT CODE
Làm bằng tay xem như đã thông qua, vậy chúng ta viết code thế nào để ra được kết quả như vậy?
Chắc là các bạn sẽ nghĩ: Ôi, dễ ẹc, đã làm bằng tay được thì record macro sẽ có code --->Thì cứ thử đi rồi biết! (đố mà gán được công thức vào Label đấy!)
Tóm lại: Khi nào có code, cứ đưa lên đây để kiểm chứng
Ẹc... Ẹc...

Câu đố này hay quá, rất tiếc chưa thấy ai giải được, mình thì giải nhiều cách cũng chưa ra, không biết các cao thủ khác có cao kiến gì không?
 
Upvote 0
Em thử "từa lưa hột dưa" luôn vẫn không tài nào gán được công thức cho Label cả!

Ghi macro thì được, mà chạy macro thì vô phương!

Mã:
Sub Macro2()
'
' Macro2 Macro
' Macro recorded 30/01/2013 by NRKH
'
    ActiveSheet.Shapes("Label 2").Select
    ExecuteExcel4Macro "FormulaR1C1(""=R1C1"")"
End Sub

Thôi, cũng mấy ngày rồi mà chưa ai có lời giải, Thầy giải luôn đi Thầy ơi, nóng lòng muốn biết kết quả quá!
 
Upvote 0
Em thử "từa lưa hột dưa" luôn vẫn không tài nào gán được công thức cho Label cả!

Ghi macro thì được, mà chạy macro thì vô phương!

Mã:
Sub Macro2()
'
' Macro2 Macro
' Macro recorded 30/01/2013 by NRKH
'
    ActiveSheet.Shapes("Label 2").Select
    ExecuteExcel4Macro "FormulaR1C1(""=R1C1"")"
End Sub

Thôi, cũng mấy ngày rồi mà chưa ai có lời giải, Thầy giải luôn đi Thầy ơi, nóng lòng muốn biết kết quả quá!
Dùng macro4 thì đúng rồi, có điều ăn tiền ở cách gán
Với macro của Nghĩa, sửa thành vầy sẽ được liền:

Mã:
Sub Macro2()
    ActiveSheet.Shapes("Label 2").Select
    ExecuteExcel4Macro [COLOR=#ff0000][B]"FORMULA(""=R1C1"")"[/B][/COLOR]
End Sub
Ẹc... Ẹc...
-----------------
Tặng luôn file viết code tổng quát
Mã:
Sub CreateLabel(ByVal Caption As String, ByVal FontName As String, _
                ByVal FontSize As Long, ByVal FontColor As Long)
  With ActiveCell
    .Value = Caption
    .Font.Name = FontName
    .Font.Size = FontSize
    .Font.ColorIndex = FontColor
    .EntireColumn.AutoFit
    .EntireRow.AutoFit
    .Parent.Labels.Add(.Left, .Top, .Width, .Height).Select
    ExecuteExcel4Macro "FORMULA(""=" & .Address(, , 2) & """)"
    ExecuteExcel4Macro "FORMULA("""")"
    .ClearContents
  End With
End Sub
Mã:
Sub Main()
  Dim Caption As String
  Caption = "Nguy" & ChrW(7877) & "n Anh Tu" & ChrW(7845) & "n"
  CreateLabel Caption, "Verdana", 20, 3
End Sub
 

File đính kèm

Upvote 0
Trong cái đề tài này:
Diễn đàn > Lập trình với Excel > Excel và các ngôn ngữ lập trình khác > Thư viện mã lập trình
> Useful functions - Các hàm hữu ích

Của levanduyet

Có đề cập tới
9) Hàm chuyển đổi số thứ tự cột thành chữ - Column number to Column letter

trong đó tác giả trích dẫn một đoạn code Convert the Excel Column Index to Letters như sau:

Mã:
Function ColumnLetter(ColumnNumber As Integer) As String
      
    '
    'example usage:
    '
    'Dim temp As Integer
    'temp = Sheets(1).Range("B2").End(xlToRight).Column
    'MsgBox "The last column of this region is " & _
    '        ColumnLetter(temp)
    '
        
If ColumnNumber <= 0 Then
    'negative column number
    ColumnLetter = ""
    
ElseIf ColumnNumber > 16384 Then
    'column not supported (too big) in Excel 2007
    ColumnLetter = ""
    
ElseIf ColumnNumber > 702 Then
    ' triple letter columns
    ColumnLetter = _
    Chr((Int((ColumnNumber-1-26-676) / 676)) Mod 676 + 65) & _
    Chr((Int((ColumnNumber-1-26) / 26) Mod 26) + 65) & _
    Chr(((ColumnNumber-1) Mod 26) + 65)

ElseIf ColumnNumber > 26 Then
    ' double letter columns
    ColumnLetter = Chr(Int((ColumnNumber-1) / 26) + 64) & _
            Chr(((ColumnNumber-1) Mod 26) + 65)
Else
    ' single letter columns
    ColumnLetter = Chr(ColumnNumber + 64)

End If

Vấn đề:
Đoạn code trên, chính tác giả đã nói rằng mình viết khởi đầu cho Excel 2003 (255 cột), sau đó nới thêm để ứng dụng cho 2007 (16384 cột).
Theo tôi thì đoạn code này được nới rộng một cách "làm cho xong". Nó không được gọn êm lắm. Xin mời các bạn viết lại cho đẹp.
Đương nhiên là cách trích từ address của cells(1, số) ra là gọn nhất. Giả sử không được dùng cách này.

(*) Xin lỗi đường đột. Tôi không biết làm như thế này có đúng tinh thần "đố vui" hay không. Nếu không đúng thì xin các bạn thứ lỗi.
 
Upvote 0
Dùng macro4 thì đúng rồi, có điều ăn tiền ở cách gán
Với macro của Nghĩa, sửa thành vầy sẽ được liền:

Mã:
Sub Macro2()
    ActiveSheet.Shapes("Label 2").Select
    ExecuteExcel4Macro [COLOR=#ff0000][B]"FORMULA(""=R1C1"")"[/B][/COLOR]
End Sub
Ẹc... Ẹc...
-----------------
Tặng luôn file viết code tổng quát
Mã:
Sub CreateLabel(ByVal Caption As String, ByVal FontName As String, _
                ByVal FontSize As Long, ByVal FontColor As Long)
  With ActiveCell
    .Value = Caption
    .Font.Name = FontName
    .Font.Size = FontSize
    .Font.ColorIndex = FontColor
    .EntireColumn.AutoFit
    .EntireRow.AutoFit
    .Parent.Labels.Add(.Left, .Top, .Width, .Height).Select
    ExecuteExcel4Macro "FORMULA(""=" & .Address(, , 2) & """)"
    ExecuteExcel4Macro "FORMULA("""")"
    .ClearContents
  End With
End Sub
Mã:
Sub Main()
  Dim Caption As String
  Caption = "Nguy" & ChrW(7877) & "n Anh Tu" & ChrW(7845) & "n"
  CreateLabel Caption, "Verdana", 20, 3
End Sub

Sao kỳ thế Thầy, sao máy em, excel 2007 lại bấm nút file của Thầy chỉ nổi lên label rồi tên label xx thôi? không có gán được địa chỉ từ ô ?
 
Upvote 0
Đương nhiên là cách trích từ address của cells(1, số) ra là gọn nhất. Giả sử không được dùng cách này.

(*) Xin lỗi đường đột. Tôi không biết làm như thế này có đúng tinh thần "đố vui" hay không. Nếu không đúng thì xin các bạn thứ lỗi.

Chắc là vầy chăng:
Mã:
Function ColumnLetter(ByVal ColIndex As Long) As String
  If ColIndex <= 26 Then
    ColumnLetter = Chr(ColIndex + 64)
  Else
    ColumnLetter = ColumnLetter((ColIndex - 1) \ 26) & Chr(((ColIndex - 1) Mod 26) + 65)
  End If
End Function
Bạn test giúp!
 
Lần chỉnh sửa cuối:
Upvote 0
Thế còn đoạn code Macro 2 thì sao?

Có thể Thầy dùng Excel 2010 nên mới thực hiện điều đó chăng? Bởi quay macro nó cũng như Thầy sửa lại thôi, bởi em đã thử sửa cái chữ FORMULA thành FORMULAR1C1.

[video=youtube;pwwsYJCqHv0]http://www.youtube.com/watch?v=pwwsYJCqHv0&amp;feature=youtu.be[/video]
 
Upvote 0
Tạo mảng gồm các chuổi không trùng nhau

- Cho trước các ký tự: 0 đến 9, A đến Z
- Ghép lại thành 1 chuổi 5 ký tự (ví dụ: 0B1B9)
Hỏi: Viết code như thế nào để tạo ra 1000 chuổi như trên mà không có chuổi nào trùng nhau?

Untitled.jpg





























(Đố vui thì đương nhiên code sẽ rất đơn giản)
 
Upvote 0
- Cho trước các ký tự: 0 đến 9, A đến Z
- Ghép lại thành 1 chuổi 5 ký tự (ví dụ: 0B1B9)
Hỏi: Viết code như thế nào để tạo ra 1000 chuổi như trên mà không có chuổi nào trùng nhau?

View attachment 97587





























(Đố vui thì đương nhiên code sẽ rất đơn giản)
Em thấy chữ cái xuất hiện trong kết quả của anh chỉ từ A-F thôi. Làm đại vầy không biết có đúng ý anh không.
PHP:
Function GetRandName()
Randomize
GetRangeName = Hex(Int(65536 * 15 * Rnd + 65536))
End Function
 
Upvote 0
Em thấy chữ cái xuất hiện trong kết quả của anh chỉ từ A-F thôi. Làm đại vầy không biết có đúng ý anh không.
PHP:
Function GetRandName()
Randomize
GetRangeName = Hex(Int(65536 * 15 * Rnd + 65536))
End Function
Cách này CHẤP NHẬN
Các bạn khác thử nghĩ giải pháp nào khác xem
 
Upvote 0
Chắc là vầy chăng:
Mã:
Function ColumnLetter(ByVal ColIndex As Long) As String
  If ColIndex <= 26 Then
    ColumnLetter = Chr(ColIndex + 64)
  Else
    ColumnLetter = ColumnLetter((ColIndex - 1) \ 26) & Chr(((ColIndex - 1) Mod 26) + 65)
  End If
End Function
Bạn test giúp!

Chỉ khác tôi một chút xíu:

If ColIndex < 1 Then
ColumnLetter = ""
 
Upvote 0
Em thấy chữ cái xuất hiện trong kết quả của anh chỉ từ A-F thôi. Làm đại vầy không biết có đúng ý anh không.
PHP:
Function GetRandName()
Randomize
GetRangeName = Hex(Int(65536 * 15 * Rnd + 65536))
End Function

Theo tôi thì lấy số ngẫu nhiên không phải là hàm độc lập. Vì vậy gói randomize vào trong hàm lấy số không phải là điều tốt.
Mỗi lần gọi hàm để lấy một số thì phải gieo số lại? Trên nguyên tắc, hàm randomize chỉ nên gọi một lần duy nhất.

Tôi chưa thử với VBA nhưng kinh nghiệm cho biết với một số các ngôn ngữ khác, hàm randomize dùng giờ hệ thống làm hạt giống. Nếu hàm gọi số ngẫu nhiên chạy rất nhanh, giờ hệ thống chưa thay đổi kịp thì số Rnd sẽ bị lặp lại.
 
Upvote 0
Theo tôi thì lấy số ngẫu nhiên không phải là hàm độc lập. Vì vậy gói randomize vào trong hàm lấy số không phải là điều tốt.
Mỗi lần gọi hàm để lấy một số thì phải gieo số lại? Trên nguyên tắc, hàm randomize chỉ nên gọi một lần duy nhất.

Tôi chưa thử với VBA nhưng kinh nghiệm cho biết với một số các ngôn ngữ khác, hàm randomize dùng giờ hệ thống làm hạt giống. Nếu hàm gọi số ngẫu nhiên chạy rất nhanh, giờ hệ thống chưa thay đổi kịp thì số Rnd sẽ bị lặp lại.
Tôi đã thử từ đầu và biết là nó không cho các kết quả duy nhất nhưng nhìn hình của anh anhtuan1066 thấy là một hàm nên mới làm như vậy.
Nếu muốn duy nhất thì phải đưa vào 1 sub hoặc dùng hàm mảng.
 
Upvote 0
Đến trang số 8 thì bó tay máy anh , em đang tập tễnh , vậy mà toàn cao thủ đánh đố nhau !
 
Upvote 0
Đến trang số 8 thì bó tay máy anh , em đang tập tễnh , vậy mà toàn cao thủ đánh đố nhau !
Bạn đọc tiêu đề không kỹ hay sao mà nói vậy? "Đố vui" chứ không phải là đánh đố
Với tiêu đề này cho mọi người vừa giải trí, vừa nâng cao khả năng hiểu biết về VBA, mình rất thích có điều chưa đủ khả năng trả lời thôi. Chứ đâu phải đánh đố nhau !
 
Upvote 0
Tôi đã thử từ đầu và biết là nó không cho các kết quả duy nhất nhưng nhìn hình của anh anhtuan1066 thấy là một hàm nên mới làm như vậy.
Nếu muốn duy nhất thì phải đưa vào 1 sub hoặc dùng hàm mảng.

Thì tùy ý mà, muốn hàm muốn SUB gì cũng được... Cái của Thắng xem như đạt yêu cầu rồi đấy, muốn chắc ăn, cùng lắm ta dùng thêm Dictionary là được... Quan trọng vẫn ở chổ tạo ra 1 chuổi ngẫu nhiên 5 ký tự
Vẫn còn 1 cách khác khá đơn giản đấy
 
Upvote 0
Cách dễ nhất để randomize chỉ xảy ra 1 lần:

Function GetRandName()
static reptd as integer
if reptd <> 1 then
Randomize
reptd = 1
end if
GetRangeName = Hex(Int(65536 * 15 * Rnd + 65536))
End Function
 
Upvote 0
Cách dễ nhất để randomize chỉ xảy ra 1 lần:

Function GetRandName()
static reptd as integer
if reptd <> 1 then
Randomize
reptd = 1
end if
GetRandName = Hex(Int(65536 * 15 * Rnd + 65536))
End Function
Không biết mọi người đã thử chưa chứ tôi thử thì thấy tuy có hạn chế nhưng vẫn có kết quả trùng.
 
Upvote 0
Không biết mọi người đã thử chưa chứ tôi thử thì thấy tuy có hạn chế nhưng vẫn có kết quả trùng.

Vụ trùng đã có Dictionary lo rồi (nếu muốn), ta đâu cần quan tâm!
Vấn đề ở đây là tạo ra được 1 chuổi gồm 5 ký tự ngẫu nhiên... và code của Thắng đã đạt rồi còn gì.
Nhưng đố bài này mình đang muốn nhắm đến 1 code khác (1 tool có sẵn) cũng có khả năng tạo ra chuổi 5 ký tự ngẫu nhiên ---> Các bạn suy nghĩ xem
(đã từng làm nhưng có khi mọi người ít để ý)
 
Upvote 0
Ý kiến của tôi chỉ nói về cách sử dụng randomize. Còn bị trùng là do thuật toán.

Theo thuật toán trên thì tỷ lệ trùng cũng tương đối không nhỏ.
Muốn giảm thiểu tỷ lệ trùng thì phải dùng đủ từ [A-Z0-9] và gọi hàm Rnd đủ 5 lần

Mã:
Function KyTuNgauNhien(ByVal soKyTu) As String
' hàm trả về chuỗi ký tự ngẫu nhiên theo độ dài soKyTu
' initialise random seed here
Static reptd As Integer
If reptd <> 1 Then
    Randomize
    reptd = 1
End If
' code here
Const KT = "0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ"
Dim i, rg As Integer, kq As String
rg = Len(KT)
kq = Space(soKyTu)
For i = 1 To soKyTu
    Mid(kq, i, 1) = Mid(KT, Int(rg * Rnd + 1), 1)
Next i
KyTuNgauNhien = kq
End Function

* Code khá luộm thuộm. Tôi nghĩ là người đố có mẹo nào đó làm rất gọn
 
Upvote 0
* Code khá luộm thuộm. Tôi nghĩ là người đố có mẹo nào đó làm rất gọn

Đương nhiên! Nếu không thì còn gọi gì là ĐỐ VUI
Ở đây, vụ trùng ta khỏi cần bàn tới đi, vì dù sao thì cũng có Dictionary đảm nhận việc này... Mình chỉ bàn về giải thuật tạo 1 chuổi với 5 ký tự ngẫu nhiên thôi
(nếu nói ra, chắc chắn ai cũng nói rằng "ĐÃ TỪNG BIẾT", có điều trong 1 thoáng chưa kịp nghĩ đến)
-----------------
Nói thêm: Nếu tôi làm bài này thì sẽ không có bất cứ dòng nào liên quan đến hàm RAND
 
Upvote 0
Gán mảng 1 chiều xuống 1 cột

Giả sử tôi có 1 mảng:
arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
mảng gồm 6 phần tử
Giờ tôi muốn gán mảng này xuống vùng A1:A6 (6 dòng, 1 cột)
Thông thường ta sẽ dùng vòng lập hoặc Transpose để biến màng 1 chiều trên thành 2 chiều (1 cột, nhiều dòng)
Xin hỏi: Có cách nào có thể gán mảng 1 chiều 6 phần tử kia xuống A1:A6 mà không cần đến vòng lập hay Transpose không?
 
Upvote 0
Giả sử tôi có 1 mảng:
arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
mảng gồm 6 phần tử
Giờ tôi muốn gán mảng này xuống vùng A1:A6 (6 dòng, 1 cột)
Thông thường ta sẽ dùng vòng lập hoặc Transpose để biến màng 1 chiều trên thành 2 chiều (1 cột, nhiều dòng)
Xin hỏi: Có cách nào có thể gán mảng 1 chiều 6 phần tử kia xuống A1:A6 mà không cần đến vòng lập hay Transpose không?

Chú Tuấn ơi, kyo thấy cách dễ nhất và củ chuối nhất là:
Mã:
[A1].Value = arr(0)
[A2].Value = arr(1)
[A3].Value = arr(2)
[A4].Value = arr(3)
[A5].Value = arr(4)
[A6].Value = arr(5)
 
Upvote 0
Chú Tuấn ơi, kyo thấy cách dễ nhất và củ chuối nhất là:
Mã:
[A1].Value = arr(0)
[A2].Value = arr(1)
[A3].Value = arr(2)
[A4].Value = arr(3)
[A5].Value = arr(4)
[A6].Value = arr(5)
Ai lại làm thế! (còn gì là ĐỐ VUI)
Mảng là nói chung chung, có thể nó chứa 1000 phần tử cũng không chừng
-------------
Ngày trước tôi từng làm theo kiểu: Gán mảng 1 chiều vào 1 ComboBox rồi lấy ngược trở ra, nó sẽ tự chuyển thành mảng 2 chiều
Tuy nhiên, với bài này thì ta chưa có ComboBox đâu nha (cũng không cho vẽ thêm bất cứ thứ gì trên sheet luôn)
 
Lần chỉnh sửa cuối:
Upvote 0
Ai lại làm thế! (còn gì là ĐỐ VUI)
Mảng là nói chung chung, có thể nó chứa 1000 phần tử cũng không chừng
-------------
Ngày trước tôi từng làm theo kiểu: Gán mảng 1 chiều vào 1 ComboBox rồi lấy ngược trở ra, nó sẽ tự chuyển thành mảng 2 chiều
Tuy nhiên, với bài này thì ta chưa có ComboBox đâu nha (cũng không cho vẽ thêm bất cứ thứ gì trên sheet luôn)
Có khi nào ...tự nhập tay ko ta???
 
Upvote 0
Đố về VBA mà đồng chí! Đương nhiên giải pháp phải là VBA chứ sao có vụ tay chân gì ở đây
Thêm nữa: Đố vui, vậy nên giải pháp cũng phải mang tính độc đáo (lạ, ít người biết)

Vậy cho em hỏi, có cần thông qua một control nào không vậy Thầy?
 
Upvote 0
Thích làm gì tùy ý, miễn không vẽ các control ấy lên bảng tính để làm nơi "đậu tàu" là được

Nếu vậy thì em làm thử như vầy:

Mã:
Private Sub CommandButton1_Click()
    Range("A1:A100").Clear
    arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
    With UserForm1.ComboBox1
        .List = arr
        Range("A1").Resize(.ListCount) = .List
    End With
End Sub
 

File đính kèm

Upvote 0
Nếu vậy thì em làm thử như vầy:

Mã:
Private Sub CommandButton1_Click()
    Range("A1:A100").Clear
    arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
    With UserForm1.ComboBox1
        .List = arr
        Range("A1").Resize(.ListCount) = .List
    End With
End Sub

Đồng chí này chơi ăn gian quá
Đã nói không vẽ ra trên bảng tính, giờ lại vẽ lên UserForm, cũng như không (bài 634 đã nói rồi mà)
---------------------
Gợi ý cho bạn 1 cách: Ghi mảng ấy vào 1 file Txt, xong đọc file txt và gán vào bảng tính (sẽ không cần vòng lập)
Tuy nhiên đây cũng chưa phải là cách hay (còn cách khác hay hơn)
 
Upvote 0
Đồng chí này chơi ăn gian quá
Đã nói không vẽ ra trên bảng tính, giờ lại vẽ lên UserForm, cũng như không (bài 634 đã nói rồi mà)
---------------------
Gợi ý cho bạn 1 cách: Ghi mảng ấy vào 1 file Txt, xong đọc file txt và gán vào bảng tính (sẽ không cần vòng lập)
Tuy nhiên đây cũng chưa phải là cách hay (còn cách khác hay hơn)

Hahaha, tại Thầy nói không cho vẽ trên sheet chứ đâu có cho nói không được vẽ trên form đâu! hahahaha
 
Upvote 0
Hahaha, tại Thầy nói không cho vẽ trên sheet chứ đâu có cho nói không được vẽ trên form đâu! hahahaha

Nói chung là: Cái chiêu gán array vào combobox rồi lấy ngược trở về người ta đã làm rồi, giờ mình làm lại thì còn gì là bí mật và độc đáo nữa
 
Upvote 0
Xin hỏi:Có cách nào có thể gán mảng 1 chiều 6 phần tử kia xuống A1:A6 mà không cần đến vòng lập hay Transpose không?
Hi Anh
[GPECODE=vb]Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True[/GPECODE]
Có dùng cái này được không anh.

Lê Văn Duyệt
 
Upvote 0
Vì trong đoạn code đó có Transpose. Vậy nếu dùng cái này thì được hả anh?

Lê Văn Duyệt

Câu đố là có 1 mảng 1 chiều cho trước, bằng cách nào chuyển thành hoặc như mảng 2 chiều mà không dùng vòng lặp, không dùng Transpose.
 
Upvote 0
Vì trong đoạn code đó có Transpose. Vậy nếu dùng cái này thì được hả anh?

Lê Văn Duyệt

Ý mình muốn nói rằng:
- Đầu tiên ta có arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban") (đầu vào)
-
Tiếp theo Duyệt lại dùng PasteSpecial gì gì đó
Vậy nên mình thắc mắc rằng: Ta chưa copy cái gì cả thì lấy cái gì để paste đây?
Nhưng nếu Duyệt nghĩ là được thì thử xem
 
Upvote 0
Nếu được dùng kiểu đó thì:
[GPECODE=vb]
arr1 = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
Dim rngSource As Range
Set rngSource = Range("B1")
rngSource .Resize(1, UBound(arr1, 1)).Value = arr1 ' Đưa các giá trị của mảng vào hàng từ vị trí B1
rngSource .Resize(1, UBound(arr1, 1)).Copy 'Copy
Range("A1").PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True 'Đưa các giá trị ra từ vị trí A1
[/GPECODE]

dovuivba_zps58cf0b97.jpg


Lê Văn Duyệt
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu được dùng kiểu đó thì:
[GPECODE=vb]
arr1 = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
Dim rngSource As Range
Set rngSource = Range("B1")
rngSource .Resize(1, UBound(arr1, 1)).Value = arr1 ' Đưa các giá trị của mảng vào hàng từ vị trí B1
rngSource .Resize(1, UBound(arr1, 1)).Copy 'Copy
Range("A1").PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True 'Đưa các giá trị ra từ vị trí A1
[/GPECODE]

Lê Văn Duyệt

Ẹc... Ẹc... xem như cũng là 1 cách hay!
 
Upvote 0
Có thưởng không Bác.

Lê Văn Duyệt

Có gì đâu mà thường với không thường. Mình nói "Đây cũng là cách hay!" vì mình thật sự chưa nghĩ ra cách này (để loại trừ)
Mọi giải pháp, miễn ra đúng kết quả đều được chấp nhận
Xem như mình chấp nhận giải phảp của Duyệt đi nhưng mà mình còn 1 cách khác nữa, gần gần giống với gợi ý của bài 640
Các bạn suy nghĩ tiếp xem
 
Upvote 0
Có gì đâu mà thường với không thường. Mình nói "Đây cũng là cách hay!" vì mình thật sự chưa nghĩ ra cách này (để loại trừ)
Mọi giải pháp, miễn ra đúng kết quả đều được chấp nhận
Xem như mình chấp nhận giải phảp của Duyệt đi nhưng mà mình còn 1 cách khác nữa, gần gần giống với gợi ý của bài 640
Các bạn suy nghĩ tiếp xem
Nói vậy thì không vẽ ra, chỉ việc tạo object mà dùng thôi, xem như xong rồi còn gì Bác? Tại vì em cứ tưởng Bác không cho dùng cách này.
Ẹc ẹc...

Lê Văn Duyệt
 
Upvote 0
[GPECODE=vb]Sub test()Dim Narr()
Narr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
[a1:a6] = Application.Transpose(Narr())
End Sub


[/GPECODE]
Hi Anh
[GPECODE=vb]Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True[/GPECODE]
Có dùng cái này được không anh.

Lê Văn Duyệt
tiêu đề ko co transpose, nếu được dùng transpose thì đâu cần gì lôi thôi nữa
 
Lần chỉnh sửa cuối:
Upvote 0
Vậy thì nghĩ cách khác đi (dù sao đáp án của mình vẫn chưa mở)
vậy tạm xài cách cùi chuối này được ko ạ!
[GPECODE=vb]Option Explicit

Sub test()
Dim Narr()
Narr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
[b1].Resize(1, 6) = Narr()
Names.Add Name:="Chuyen", RefersTo:=[b1:g1]
[s1:s6].FormulaArray = "=Index(Chuyen, 1, Row())"
[s1:s6].Copy
[a1].PasteSpecial Paste:=xlPasteValues
[b1:g1].Clear
[s1:s6].Clear


End Sub[/GPECODE]
 

File đính kèm

Upvote 0
vậy tạm xài cách cùi chuối này được ko ạ!
[GPECODE=vb]Option Explicit

Sub test()
Dim Narr()
Narr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
[b1].Resize(1, 6) = Narr()
Names.Add Name:="Chuyen", RefersTo:=[b1:g1]
[s1:s6].FormulaArray = "=Index(Chuyen, 1, Row())"
[s1:s6].Copy
[a1].PasteSpecial Paste:=xlPasteValues
[b1:g1].Clear
[s1:s6].Clear


End Sub[/GPECODE]

Nói cho cùng thì cách này cũng gần giống với cách của Lê Văn Duyệt đã làm: "Mượn bảng tính làm nơi tạm trú"
Nghĩ cách khác thôi!
------------
Đương nhiên giải thuật vẫn sẽ là: Mượn cái gì đó làm nơi tạm trú, xong lấy ngược trở ra
Vấn đề: cái gì đó là cái gì sao cho nó... hay hay chút (ảo ảo chút) ---> Đến mức không nhìn thấy bằng mắt thường được
 
Lần chỉnh sửa cuối:
Upvote 0
"Cái gì đó" có thể là cái listbox chăng?
 
Upvote 0
Cách củ chuối vậy:
[GPECODE=vb]
Dim arrSource As Variant
Dim arrAfterTranspose As Variant

arrSource = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
Range("C1").Resize(1, UBound(arrSource, 1) + 1).Value = arrSource 'Đưa mảng trên ra tại ô C1 theo chiều ngang
With Range("A1:A" & (UBound(arrSource, 1) + 1))
.Formula = "=ROW()-1" ' Chỉ là công thức phụ
End With
With Range("B1:B" & (UBound(arrSource, 1) + 1))
.FormulaR1C1 = "=OFFSET(R1C3,0," & "RC[-1])" 'Công thức để lấy các giá trị của mảng đã đưa ra tại C1
End With
arrAfterTranspose = Range("B1").Resize(UBound(arrSource, 1) + 1, 1) 'Đưa các giá trị vào mảng
Range("A1").Resize(UBound(arrSource, 1) + 1, 1) = arrAfterTranspose 'Đưa mảng ra tại ô A1 theo chiều dọc
[/GPECODE]

Lê Văn Duyệt
 
Lần chỉnh sửa cuối:
Upvote 0
Em cũng tham gia 1 cách: Không vòng lặp, không Transpose
Mã:
Sub Test()
    Dim Str As String
    Dim Arr
    Arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
    Str = """" & VBA.Join(Arr, """;""") & """"
    Range("A1").Resize(UBound(Arr), 1).FormulaArray = "=INDEX({" & Str & "},ROW())"
End Sub
 
Upvote 0
Vui quá, cũng tham gia

[GPECODE=vb]
Dim Arr
Arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban", "quy lam", "ban oi")
Range("A1").Resize(UBound(Arr) + 1, 1).FormulaArray = "={""" & Join(Arr, """;""") & """}"
[/GPECODE]
---------------
Nếu cần dùng cho cả về sau thì ta thêm luôn Name

[GPECODE=vb]
Dim Arr, s
Arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban", "quy lam", "ban oi")
s = "={""" & Join(Arr, """;""") & """}"
ThisWorkbook.Names.Add Name:="myArr", RefersTo:=s
Range("A1").Resize(UBound(Arr) + 1, 1).FormulaArray = "=myArr"
[/GPECODE]
 
Lần chỉnh sửa cuối:
Upvote 0
Vui quá, cũng tham gia

[GPECODE=vb]
Dim Arr
Arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban", "quy lam", "ban oi")
Range("A1").Resize(UBound(Arr) + 1, 1).FormulaArray = "={""" & Join(Arr, """;""") & """}"
[/GPECODE]
---------------
Nếu cần dùng cho cả về sau thì ta thêm luôn Name

[GPECODE=vb]
Dim Arr, s
Arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban", "quy lam", "ban oi")
s = "={""" & Join(Arr, """;""") & """}"
ThisWorkbook.Names.Add Name:="myArr", RefersTo:=s
Range("A1").Resize(UBound(Arr) + 1, 1).FormulaArray = "=myArr"
[/GPECODE]
----------------------
Em cũng tham gia 1 cách: Không vòng lặp, không Transpose
Mã:
Sub Test()
    Dim Str As String
    Dim Arr
    Arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
    Str = """" & VBA.Join(Arr, """;""") & """"
    Range("A1").Resize(UBound(Arr), 1).FormulaArray = "=INDEX({" & Str & "},ROW())"
End Sub
Chấp nhận các giải pháp
Tuy nhiên, các bạn khác vẫn còn cơ hội
Ẹc... Ẹc...
 
Upvote 0
----------------------

Chấp nhận các giải pháp
Tuy nhiên, các bạn khác vẫn còn cơ hội
Ẹc... Ẹc...

Thử chơi cách "quái đản"

[GPECODE=vb]
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, source As Any, ByVal Length As Long)

Sub Test()
Dim Arr, Arr2, bArr() As Byte
Arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban", "quy lam", "ban oi")
ReDim Arr2(LBound(Arr) To UBound(Arr), 1 To 1)

CopyMemory Arr2(LBound(Arr2), 1), Arr(LBound(Arr)), (UBound(Arr) + 1) * 16
Range("A1").Resize(UBound(Arr) + 1, 1).Value = Arr2

ReDim bArr(1 To (UBound(Arr) + 1) * 16)
CopyMemory Arr2(LBound(Arr2), 1), bArr(1), (UBound(Arr) + 1) * 16
End Sub
[/GPECODE]

---------------------

Cất "nhờ" vào bộ nhớ đệm

[GPECODE=vb]
Dim Arr
Arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban", "quy lam", "ban oi")
With CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
.SetText Join(Arr, vbCrLf)
.PutInClipboard
End With
Range("A1").PasteSpecial xlPasteAll
[/GPECODE]
 
Lần chỉnh sửa cuối:
Upvote 0
----------------------

Chấp nhận các giải pháp
Tuy nhiên, các bạn khác vẫn còn cơ hội
Ẹc... Ẹc...
sản phảm của bác Siwtom
[GPECODE=vb]Sub test()Dim Narr(), chuoi As String
Narr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
chuoi = Join(Narr(), """;""")
[a1:a6].FormulaArray = "= {""" & chuoi & """}"
End Sub


[/GPECODE]
 
Upvote 0
Cất "nhờ" vào bộ nhớ đệm

[GPECODE=vb]
Dim Arr
Arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban", "quy lam", "ban oi")
With CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
.SetText Join(Arr, vbCrLf)
.PutInClipboard
End With
Range("A1").PasteSpecial xlPasteAll
[/GPECODE]

Chính xác là em muốn nói đến cái này đây. Em nghĩ tốc độ có thể nhanh hơn phương pháp dùng công thức
-------------
Đây là đáp án của em:
Mã:
Sub Arr1DToColumn(ByVal arr1D, ByVal Target As Range)
  Dim text As String
  On Error GoTo ExitSub
  text = Join(arr1D, vbLf)
  With CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    .Clear
    .SetText text
    .PutInClipboard
  End With
  Target.PasteSpecial
ExitSub:
End Sub
Mã:
Sub Main()
  Dim arr
  arr = Array("Giai", "phap", "Excel", "cong cu", "tuyet voi", "cua ban")
  Arr1DToColumn arr, Sheet1.Range("A1")
End Sub
Giải thuật:
- Nối mảng lại bẳng ký tự ngắt dòng (vbLf)
- Cho chuổi vừa nối vào Clipboard
- Giờ trên bảng tính, chỉ việc chọn 1 cell bất kỳ rồi Ctrl + V sẽ có kết quả
Ẹc... Ẹc...
------------------
Áp dụng mở rộng:
Với 1 file txt được lưu từ file Excel (dòng cách dòng bằng ký tự vbCrLf và cột cách cột bằng ký tự vbTab), ta có thể áp dụng cách này để đưa dữ liệu từ txt vào Excel 1 cách dễ dàng. Cách làm như sau:
- Đọc file text
- Cho vào Clipboard
- Ctrl + V để paste vào Excel
 
Lần chỉnh sửa cuối:
Upvote 0
Chiêu này từ nào giờ em chưa rờ đến.
Nếu cất nhờ vào bộ nhớ liệu nó có giới hạn nào không anh?

Ngoài ra góp ý anh, là mai mốt cho đề bài kỹ hơn

Lê Văn Duyệt
 
Upvote 0
Chiêu này từ nào giờ em chưa rờ đến.
Nếu cất nhờ vào bộ nhớ liệu nó có giới hạn nào không anh?
Ai biết đâu nè! Khi nào có dịp xài đến mình sẽ thí nghiệm
Ngoài ra góp ý anh, là mai mốt cho đề bài kỹ hơn
Lê Văn Duyệt

Xin lỗi! Tại không lường hết các tình huống ấy mà
Ẹc... Ẹc...
 
Upvote 0
Đương nhiên! Nếu không thì còn gọi gì là ĐỐ VUI
Ở đây, vụ trùng ta khỏi cần bàn tới đi, vì dù sao thì cũng có Dictionary đảm nhận việc này... Mình chỉ bàn về giải thuật tạo 1 chuổi với 5 ký tự ngẫu nhiên thôi
(nếu nói ra, chắc chắn ai cũng nói rằng "ĐÃ TỪNG BIẾT", có điều trong 1 thoáng chưa kịp nghĩ đến)
-----------------
Nói thêm: Nếu tôi làm bài này thì sẽ không có bất cứ dòng nào liên quan đến hàm RAND

Hình như bài này vẫn chưa có đáp án của tác giả, mọi người làm cho vui cửa vui nhà, còn không, tác giả giải luôn cho mọi người chiêm ngưỡng.
 
Upvote 0
Hình như bài này vẫn chưa có đáp án của tác giả, mọi người làm cho vui cửa vui nhà, còn không, tác giả giải luôn cho mọi người chiêm ngưỡng.

Trời ơi! Chẳng thấy ai hỏi, xém quên
Anh vào cửa sổ Immediate, gõ dòng lệnh này xem:
Mã:
[B]?Mid(CreateObject("Scripting.FileSystemObject").GetTempName, 4, 5) [/B]
 
Upvote 0
Trời ơi! Chẳng thấy ai hỏi, xém quên
Anh vào cửa sổ Immediate, gõ dòng lệnh này xem:
Mã:
[B]?Mid(CreateObject("Scripting.FileSystemObject").GetTempName, 4, 5) [/B]

Hi, buộc phải có vòng lặp hả bạn?
Mình thử với code này:
Mã:
Sub abc()    
Application.ScreenUpdating = False
    Dim i As long
    On Error Resume Next
    Do Until Err > 0
        i = i + 1
        Range("A" & i) = CreateObject("Scripting.FileSystemObject").GetTempName
    Loop
    Application.ScreenUpdating = True
    MsgBox i
End Sub


Chạy trên Excel2010 miệt mài luôn, nếu không giới hạn i, lọc duy nhất thấy cũng có trùng. Cũng hay!
 
Lần chỉnh sửa cuối:
Upvote 0
Hi, buộc phải có vòng lặp hả bạn?
Mình thử với code này:
Mã:
Sub abc()    
Application.ScreenUpdating = False
    Dim i As long
    On Error Resume Next
    Do Until Err > 0
        i = i + 1
        Range("A" & i) = CreateObject("Scripting.FileSystemObject").GetTempName
    Loop
    Application.ScreenUpdating = True
    MsgBox i
End Sub


Cũng hay!
Cái này chuyên dùng để tạo 1 file tạm (có tên ngẫu nhiên) trên đĩa cứng. Giờ ta "chế" lại thôi
Có điều chạy 1 số lần nhất định nào đó thì sẽ có trùng. Vậy nên anh phải kết hợp với Dictionary nữa thì mới hoàn chỉnh
 
Upvote 0
Khuấy động một tí cho vui!

Làm sao để tạo được một mảng như thế này:
Mã:
For i = 1 To 10
    ' .....................
    Arr(i).Value = Cells(i, 1)
    Arr(i).Name = Cells(i, 2)
Next i

và sử dụng:
Mã:
MsgBox UBound(Arr)
MsgBox Arr(8).Name
 
Upvote 0
Khuấy động một tí cho vui!

Làm sao để tạo được một mảng như thế này:
Mã:
For i = 1 To 10
    ' .....................
    Arr(i).Value = Cells(i, 1)
    Arr(i).Name = Cells(i, 2)
Next i

và sử dụng:
Mã:
MsgBox UBound(Arr)
MsgBox Arr(8).Name

Mình đã từng xài cái chiêu tương tự thế này rồi... Có điều chưa biết cái mà mình xài có giống như ý của anh không?
(chắc là giống)
Ẹc... Ẹc....
 
Upvote 0
Khuấy động một tí cho vui!

Làm sao để tạo được một mảng như thế này:
Mã:
For i = 1 To 10
    ' .....................
    Arr(i).Value = Cells(i, 1)
    Arr(i).Name = Cells(i, 2)
Next i

và sử dụng:
Mã:
MsgBox UBound(Arr)
MsgBox Arr(8).Name

Kiểu này em thường xuyên làm với UserForm, đặt một biến mảng 1 chiều với các phần tử là các TextBox hay ComboBox, ...

Nói như thế chắc anh ThanhLanh biết em biết cách thực hiện rồi chứ?
 
Upvote 0
Kiểu này em thường xuyên làm với UserForm, đặt một biến mảng 1 chiều với các phần tử là các TextBox hay ComboBox, ...

Nói như thế chắc anh ThanhLanh biết em biết cách thực hiện rồi chứ?

Đó cũng là một hướng nhưng mình không phải dùng cách đó.
Vậy nói thêm: Không được dùng TextBox, ComboBox, ListBox, ..., các đối tượng tương tự trên Form
 
Upvote 0
Đó cũng là một hướng nhưng mình không phải dùng cách đó.
Vậy nói thêm: Không được dùng TextBox, ComboBox, ListBox, ..., các đối tượng tương tự trên Form

Vậy chỉ có làm các Define Name tự động thôi à!

(Mà nếu như vậy thì làm trực tiếp trên Range chứ sao phải qua công đoạn Array chi cho phức tạp vậy ta?)
 
Lần chỉnh sửa cuối:
Upvote 0
Vậy chỉ có làm các Define Name tự động thôi à!
Để ý cái Arr(i).ValueArr(i).Name thì biết các phần tử của Arr phải là BIẾN ĐỐI TƯỢNG (và điều đương nhiên là phải có động tác SET.. gì gì đó)
Vậy hãy nghĩ đến đối tượng nào có 2 thuộc tính màu đỏ ở trên là được rồi
Mà nếu như vậy thì làm trực tiếp trên Range chứ sao phải qua công đoạn Array chi cho phức tạp vậy ta?)
Thứ nhất: Đố vui
Thứ hai: Không phải là không có ứng dụng (tôi xài vụ này hoài)
 
Upvote 0
các phần tử của Arr phải là BIẾN ĐỐI TƯỢNG

chưa hẳn thế

Khuấy động một tí cho vui!

Làm sao để tạo được một mảng như thế này:
Mã:
For i = 1 To 10
    ' .....................
    Arr(i).Value = Cells(i, 1)
    Arr(i).Name = Cells(i, 2)
Next i

và sử dụng:
Mã:
MsgBox UBound(Arr)
MsgBox Arr(8).Name

Ngồi một lúc là nghĩ ra cả đống thôi.

Toàn bộ code của class module clsTest
Mã:
Public Value
Public Name

module1
Mã:
Public Type MYSTRUCT
    Value As String
    Name As String
End Type

Sub hichic()
Dim Arr(1 To 10) As New clsTest, tmp(1 To 10) As MYSTRUCT
    For i = 1 To 10
        Arr(i).Value = Cells(i, 1)
        Arr(i).Name = Cells(i, 2)
        
        tmp(i).Value = Cells(i, 1)
        tmp(i).Name = Cells(i, 2)
    Next i
    
    MsgBox UBound(Arr)
    MsgBox Arr(8).Name
    
    MsgBox UBound(tmp)
    MsgBox tmp(8).Value
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Để ý cái Arr(i).ValueArr(i).Name thì biết các phần tử của Arr phải là BIẾN ĐỐI TƯỢNG (và điều đương nhiên là phải có động tác SET.. gì gì đó)
Vậy hãy nghĩ đến đối tượng nào có 2 thuộc tính màu đỏ ở trên là được rồi

Thứ nhất: Đố vui
Thứ hai: Không phải là không có ứng dụng (tôi xài vụ này hoài)

Hỏng biết có ứng dụng gì, nhưng nó đại loại là như vầy nè Thầy ơi:

Mã:
Sub test()
Dim Arr(1 To 3) As Object
Dim Rng As Range, i As Byte
For i = 1 To 3
    Set Rng = Cells(i, 1)
    Set Arr(i) = Rng
    Arr(i).Value = Cells(i, 2).Value
    Arr(i).Name = Cells(i, 3).Value
Next
End Sub
 
Upvote 0
chưa hẳn thế



Ngồi một lúc là nghĩ ra cả đống thôi.

Toàn bộ code của class module clsTest
Mã:
Public Value
Public Name

module1
Mã:
Public Type MYSTRUCT
    Value As String
    Name As String
End Type

Sub hichic()
Dim Arr(1 To 10) As New clsTest, tmp(1 To 10) As MYSTRUCT
    For i = 1 To 10
        Arr(i).Value = Cells(i, 1)
        Arr(i).Name = Cells(i, 2)
        
        tmp(i).Value = Cells(i, 1)
        tmp(i).Name = Cells(i, 2)
    Next i
    
    MsgBox UBound(Arr)
    MsgBox Arr(8).Name
    
    MsgBox UBound(tmp)
    MsgBox tmp(8).Value
End Sub

Em dám cá với anh rằng anh thanhlanh hổng phải nói đến cái này
-------------------------
Hỏng biết có ứng dụng gì, nhưng nó đại loại là như vầy nè Thầy ơi:

Mã:
Sub test()
Dim Arr(1 To 3) As Object
Dim Rng As Range, i As Byte
For i = 1 To 3
    Set [B]Rng [/B]= Cells(i, 1)
    Set Arr(i) = Rng
    Arr(i).Value = Cells(i, 2).Value
    Arr(i).Name = Cells(i, 3).Value
Next
End Sub
Vậy thì thêm biến Rng để làm giống gì?
 
Upvote 0
Vậy thì thêm biến Rng để làm giống gì?

Thì lúc đầu em nghĩ cho nó hiểu đối tượng nó đang nạp vào là dạng Range, nên mới để như vậy, nhưng xem ra nó cũng tự hiểu đối tượng của nó đang nạp là gì!

Nhưng nếu làm như thế thì em chẳng cần phải làm mảng, vì đối tượng nó nhận cũng là dạng RANGE nên ta trực tiếp làm trên range cho chắc ăn! Nếu nói mảng mà thực hiện cho tốc độ cao trong trường hợp này thì đó là một sai lầm!
 
Lần chỉnh sửa cuối:
Upvote 0
Thì lúc đầu em nghĩ cho nó hiểu đối tượng nó đang nạp vào là dạng Range, nên mới để như vậy, nhưng xem ra nó cũng tự hiểu đối tượng của nó đang nạp là gì!

Nhưng nếu làm như thế thì em chẳng cần phải làm mảng, vì đối tượng nó nhận cũng là dạng RANGE nên ta trực tiếp làm trên range cho chắc ăn! Nếu nói mảng mà thực hiện cho tốc độ cao trong trường hợp này thì đó là một sai lầm!

Có thể Nghĩa hiểu sai vấn đề rồi (cũng đâu có ai nói gì liên quan đến tốc độ trong này đâu)
Như đã nói ở trên: Đây là ĐỐ VUI
Còn chuyện ứng dụng thì thiếu gì... chẳng hạn tôi muốn tạo ra 1 mảng mà các phần tử trong đó là Range (tôi muốn gom các Range có cùng tính chất nào đó vào chung 1 mảng rồi xử lý 1 lần)
-----------
Với code của Nghĩa, chỉ cần Dim Arr(1 To 3) As Range là được rồi
 
Upvote 0
Có thể Nghĩa hiểu sai vấn đề rồi (cũng đâu có ai nói gì liên quan đến tốc độ trong này đâu)
Như đã nói ở trên: Đây là ĐỐ VUI
Còn chuyện ứng dụng thì thiếu gì... chẳng hạn tôi muốn tạo ra 1 mảng mà các phần tử trong đó là Range (tôi muốn gom các Range có cùng tính chất nào đó vào chung 1 mảng rồi xử lý 1 lần)
-----------
Với code của Nghĩa, chỉ cần Dim Arr(1 To 3) As Range là được rồi

Trong biến đối tượng, kể cả là đối tượng Range, nếu em nhớ không lầm thì chỉ chứa max có 254 mục mà thôi. Còn nếu ta làm trực tiếp trên Range thì theo RC của cells thôi.
 
Upvote 0
Upvote 0
Thầy thử nghiệm với cái này nha:

Mã:
    Dim Arr(1 To 1000) As Range, i As [COLOR=#ff0000][B]Byte[/B][/COLOR]
    For i = 1 To [COLOR=#ff0000][B]254[/B][/COLOR]
        Set Arr(i) = Cells(i, 1)
        Arr(i).Value = Cells(i, 2).Value
        Arr(i).Name = Cells(i, 3).Value
    Next

Thầy thay cái số 254 thành số lớn hơn xem nó có chạy được không ạ?

Đó là tại Nghĩa thôi!
Ai biểu Dim i as Byte làm chi
Tôi chả bao giờ chơi cái Byte này cả (trừ những trường hợp đặc biệt) ---> Cứ Long cho chắc
 
Upvote 0
chưa hẳn thế



Ngồi một lúc là nghĩ ra cả đống thôi.

Toàn bộ code của class module clsTest
Mã:
Public Value
Public Name

module1
Mã:
Public Type MYSTRUCT
    Value As String
    Name As String
End Type

Sub hichic()
Dim Arr(1 To 10) As New clsTest, tmp(1 To 10) As MYSTRUCT
    For i = 1 To 10
        Arr(i).Value = Cells(i, 1)
        Arr(i).Name = Cells(i, 2)
        
        tmp(i).Value = Cells(i, 1)
        tmp(i).Name = Cells(i, 2)
    Next i
    
    MsgBox UBound(Arr)
    MsgBox Arr(8).Name
    
    MsgBox UBound(tmp)
    MsgBox tmp(8).Value
End Sub

Hôm sau có đố thì ghi chú trừ anh siwtom ra, hi hi.

Nhưng em làm khác tí:

Code trong Class1:

Mã:
Public Name As String
Public Value As Long

Code trong Module:

Mã:
Sub Test()
    Dim Arr(1 To 10) As Class1
    Dim i As Long
    For i = 1 To 10
        Set Arr(i) = New Class1
        Arr(i).Value = Cells(i, 1)
        Arr(i).Name = Cells(i, 2)
    Next i
    MsgBox UBound(Arr)
    MsgBox Arr(8).Name
End Sub

Đây là một trong những bài học vỡ lòng về Class
Cám ơn anh, cám ơn mọi người đã quan tâm.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Xây dựng hàm TRIM trong VBA mà không cần vòng lập

Như ta đã biết, hàm TRIM trên bảng tính khác với TRIM trong VBA
TRIM trong VBA chỉ remove khoảng trắng ở đầu và cuối chuổi (ở giữa chuổi nó không làm)
Thông thường khi muốn dùng TRIM giống như TRIM trên bảng tính thì:
- Hoặc là dùng WorksheetFunction.Trim
- Hoặc là tự viết 1 UDF (thường dùng trong các ứng dụng khác)
Với UDF, khi xây dựng nó sẽ không tránh khỏi phải thông qua 1 vòng lập
----------------
Vậy xin hỏi: Có thể dùng code VBA để xây dựng hàm TRIM giống như TRIM trên bảng tính (tức là nó có khả năng xóa mọi khoảng trắng thừa trong chuổi kể cả đầu, cuối và giữa chuổi) mà không cần đến vòng lập không?
(Đương nhiên cũng không dùng WorksheetFunction)
---------------------------------------------
Lưu ý: nghỉ chơi với anh siwtom
Ẹc.... Ẹc...
 
Lần chỉnh sửa cuối:
Upvote 0
Như ta đã biết, hàm TRIM trên bảng tính khác với TRIM trong VBA
TRIM trong VBA chỉ remove khoảng trắng ở đầu và cuối chuổi (ở giữa chuổi nó không làm)
Thông thường khi muốn dùng TRIM giống như TRIM trên bảng tính thì:
- Hoặc là dùng WorksheetFunction.Trim
- Hoặc là tự viết 1 UDF (thường dùng trong các ứng dụng khác)
Với UDF, khi xây dựng nó sẽ không tránh khỏi phải thông qua 1 vòng lập
----------------
Vậy xin hỏi: Có thể dùng code VBA để xây dựng hàm TRIM giống như TRIM trên bảng tính (tức là nó có khả năng xóa mọi khoảng trắng thừa trong chuổi kể cả đầu, cuối và giữa chuổi) mà không cần đến vòng lập không?
(Đương nhiên cũng không dùng WorksheetFunction)
---------------------------------------------
Lưu ý: nghỉ chơi với anh siwtom
Ẹc.... Ẹc...

Có liên quan gì đến cái này không Thầy?

CreateObject("vbscript.regexp")
 
Upvote 0
Nhưng ndu đã suýt đúng khi nói "các phần tử của Arr phải là BIẾN ĐỐI TƯỢNG". Ec, ec...
Msgbox TypeName(Arr) => Object()

Trông xa tưởng là mèo, lại gần hóa ra chim.

Em thì đang nghĩ anh nói đến Arr là Range
Vì thật ra nếu làm giống như Nghĩa đã làm cũng hoàn toàn đáp ứng được yêu cầu anh đưa ra rồi
-------------------
Có liên quan gì đến cái này không Thầy?

CreateObject("vbscript.regexp")
Cứ tùy ý sử dụng nếu thấy nó có.. "liên quan"
Ẹc... ẹc...
 
Upvote 0
Như ta đã biết, hàm TRIM trên bảng tính khác với TRIM trong VBA
TRIM trong VBA chỉ remove khoảng trắng ở đầu và cuối chuổi (ở giữa chuổi nó không làm)
Thông thường khi muốn dùng TRIM giống như TRIM trên bảng tính thì:
- Hoặc là dùng WorksheetFunction.Trim
- Hoặc là tự viết 1 UDF (thường dùng trong các ứng dụng khác)
Với UDF, khi xây dựng nó sẽ không tránh khỏi phải thông qua 1 vòng lập
----------------
Vậy xin hỏi: Có thể dùng code VBA để xây dựng hàm TRIM giống như TRIM trên bảng tính (tức là nó có khả năng xóa mọi khoảng trắng thừa trong chuổi kể cả đầu, cuối và giữa chuổi) mà không cần đến vòng lập không?
(Đương nhiên cũng không dùng WorksheetFunction)
---------------------------------------------
Lưu ý: nghỉ chơi với anh siwtom
Ẹc.... Ẹc...

Như thế này có được không ạ
Mã:
Function UdfTrim(Str As String)
With CreateObject("Vbscript.RegExp")
    .Global = True
    .Pattern = "\s{2,}"
    Str = .Replace(Str, " ")
End With
    UdfTrim = Trim(Str)
End Function
 
Upvote 0
Như thế này có được không ạ
Mã:
Function UdfTrim(Str As String)
With CreateObject("Vbscript.RegExp")
    .Global = True
    .Pattern = [COLOR=#ff0000]"\s{2,}"[/COLOR]
    Str = .Replace(Str, " ")
End With
    UdfTrim = Trim(Str)
End Function

Chính xác là cái đỏ đỏ ấy rồi còn gi
(dhn46 cũng là chuyên gia về RegExp, lý ra cũng phải cho nghỉ chơi sớm)
 
Upvote 0
Vầy cũng được mà
Mã:
.Pattern = " +"
 
Upvote 0
Quả thật, cái "ngôn ngữ" của thằng ".Pattern" này nó có nhiều cái mà mình chẳng biết quy luật cụ thể là như thế nào cả!
Reg thì khó nhưng với những dạng chuỗi như thế này thì anh Nghĩa có thể hiểu "dễ" như sau

Với
Mã:
.Pattern = " +"
+/ Dấu cộng là lặp lại phần đằng trước từ 1 lần trở lên, => phần đằng trước là dấu cách tương ứng mẫu (\s). (cái này tương ứng "\s+") => Trong đoạn Str cứ chỗ nào có 1 dấu cách trở lên thì đánh dấu nó lại
+/ Dùng .replace để thay thế phần đánh dấu đó.

Với
Mã:
.Pattern = "\s{2,}"
thì anh hiểu như sau
+/ mẫu \s là dấu cách
+/ {x,} => Trong đoạn Str cứ chỗ nào lặp lại phía trước (là dấu cách) ít nhất 2 lần (từ 2 dấu cách trở lên) thì đánh dấu (1 dấu cách thì không đánh dấu)
+/ Dùng Replace để thay thế

Những bài viết về Reg của bác SiwTom rất hay anh có thể tham khảo
(Bài viết có cả chân dài, chân ngắn... sinh động và vô cũng lôi cuốn, anh tìm hiểu xem sao nhé . Hihi)
 
Upvote 0
Em dám cá với anh rằng anh thanhlanh hổng phải nói đến cái này
-------------------------

Tôi cũng nghĩ là thanhlanh không "lường" tới những cái này.
Nhưng người ta đố thì mình cứ "dự thi" thôi.

Nói cho cùng thì đó là "cái gì đó" mà có ít nhất là 2 trường giá trị là Value và Name.
Tôi nói 2 trường chứ không nói 2 thuộc tính. Nhưng thường thì khi thiết kế đối tượng (class) thì những trường của nó nên là Private. Lúc đó mọi truy cập tới data đều phải thông qua các thuộc tính hoặc phương thức. Người dùng code không thể trực tiếp thay đổi giá trị của các trường được.

Vậy chỉ có thể là 2 cấu trúc: record hoặc object (class)
 
Upvote 0
Hôm sau có đố thì ghi chú trừ anh siwtom ra, hi hi.

Nhưng em làm khác tí:

Code trong Class1:

Mã:
Public Name As String
Public Value As Long

Code trong Module:

Mã:
Sub Test()
    Dim Arr(1 To 10) As Class1
    Dim i As Long
    For i = 1 To 10
        Set Arr(i) = New Class1
        Arr(i).Value = Cells(i, 1)
        Arr(i).Name = Cells(i, 2)
    Next i
    MsgBox UBound(Arr)
    MsgBox Arr(8).Name
End Sub

Đây là một trong những bài học vỡ lòng về Class
Cám ơn anh, cám ơn mọi người đã quan tâm.

Thôi chết rồi. Gửi bài xong mới thấy là thanhlanh cũng có mưu đồ dùng class
 
Upvote 0

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

Back
Top Bottom