Vấn đề tô màu gặp khi sử dụng code trong Record Macro của excel

Xin chào tất cả các bạn có tinh thần ham học và tự học VBA
Với những người tự học VBA thì việc đọc và sao chép code của chức năng Record Macro là điều không có gì xa lạ. (Đó gần như là 1 kỹ năng cần phải có khi tự học VBA)
Tuy nhiên đôi khi code trong Record Macro lại không cho ta kết quả như ý khi áp dụng vào 1 vấn đề tương tự
Và tôi xin chia sẻ với các bạn 1 tình huống như sau:
Hôm trước trong lúc làm việc tôi phát sinh nhu cầu cần 1 code để Đánh dấu x vào cột I, cho những ô ở cột F và G có .Font.Color là màu xanh
(chú thích thêm: là việc bôi màu xanh cho các ô ở cột F và G được thực hiện ở thao tác chọn Font màu trên Tab Home của Excel)

Về tư duy để code cho việc này thì khá rõ ràng:
Bước 1. Tìm dòng cuối của bảng tính
Bước 2. Chạy từ dòng đầu tới dòng cuối bằng For ...to
Bước 3. Đặt điều kiện trong vòng lặp là If Cells (i,6)màu xanh thì Cell(i,9).Value = "x"

Vấn đề cần xử lý ở code này là xác định các ô có màu xanh. Làm thế nào để code xác định được ô có màu xanh??
Để trả lời câu hỏi này. Như 1 thói quen , tôi sử dụng Record Macro cho thao tác bôi màu xanh cho ô A1. Và code của việc record macro cho kết quả như sau:
Mã:
Range("A1").Select
    With Selection.Font
        .Color = -1003520
        .TintAndShade = 0
    End With
Như các bạn thấy, record macro đã cho ra kết quả của việc bôi màu xanh ô A1. Dựa vào kết quả của code tôi đã suy luận rằng các ô màu xanh là các ô có .Font.Color = -1003520.
Từ suy luận này tôi đã đưa vào code của mình như sau:
Mã:
Sub danhdaux()
Dim lr As Long
With Sheets("test")
Sheets("test").Select
lr = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 1 To lr
    If Cells(i, 6).Font.Color = -1003520 Or _
        Cells(i, 7).Font.Color = -1003520 Then
        Cells(i, 9).Value = "x"
    End If
Next i
End With
End Sub
Code trên hòan toàn mạch lạc về tư duy như tôi đã nêu ở trên. Tuy nhiên thực tế là code không hề cho ra kết quả mặc dù code có chạy và không báo lỗi
Từ đây tôi rút ra 1 kết luận là việc copy các code trong Record Macro để sử dụng đôi khi không đúng với 1 vài tính huống.
Cảm ơn các bạn đã đọc và mong nhận được các ý kiến, thắc mắc hoặc giải thích thêm về bài của tôi. Để từ đó chúng ta có được những bài học bổ ích hơn khi làm việc với VBA
 
Sửa lần cuối:

tuhocvba

Administrator
Thành viên BQT
Bạn thân mến, macro ở trên cho code có giá trị tham khảo là:
Mã:
Cells(i, 7).Font.Color = -1003520
Phần quan tâm là code tô màu .Font.Color, nó đúng.

Vấn đề ở đây là số -1003520, mình sẽ giải thích ở bài viết khác.
Trước đây Excel 2003 dùng ColorIndex và chẳng có vấn đề gì xảy ra, sau đó thì Excel không còn dùng thuộc tính này nữa, thay vào đó là Color.
Để giải quyết triệt để vấn đề này, bây giờ chúng ta không dùng số để tô màu nữa, ta đi thẳng vào bản chất của vấn đề về màu là RGB.
Không chỉ là màu cho font, màu cho cells cũng bị vậy. Liên quan tới màu sắc, hãy dùng RGB. Nó luôn luôn đúng, trong tất cả các phiên bản excel, vì màu sắc RGB là một thông số cơ bản, được sử dụng cả trong HTML (thiết kế giao diện web).

Bạn hãy dùng một chương trình khác để tô màu. Ví dụ:
Mã:
Cells(i, 7).Font.Color = RGB(0, 0, 255)
Bây giờ bạn dùng một chương trình khác để thí nghiệm lại:
Mã:
if Cells(i, 7).Font.Color = RGB(0, 0, 255) then
....
End if
Tham khảo bảng mã màu RGB tại đây:
Mã:
https://bietmaytinh.com/bang-ma-mau/
 

vbano1

SMod
Thành viên BQT
Từ đây tôi rút ra 1 kết luận là việc copy các code trong Record Macro để sử dụng đôi khi không đúng với 1 vài tính huống.
Thật ra thì Macro không sai, cái số -1003520, thì nó vẫn ra màu xanh. Bằng chứng là nếu mình chạy macro sau:
Mã:
Sub Macro1()
    Range("C3").Select
With Selection.Font
.Color = -1003520
.TintAndShade = 0 'Chỉnh độ sáng, không cần thiết, bỏ đi cũng được
End With
End Sub
Thì nó vẫn tô màu xanh cho chữ ở ô C3. Vì vậy không thể nói là code macro sai.
Tuy nhiên làm ngược lại thì không làm được.
Mã:
Sub test()
    If ThisWorkbook.Sheets(1).Range("C3").Font.Color = -1003520 Then MsgBox "OK"
End Sub
Là bởi vì VBA nó không hiểu con số đó nếu quy ra RGB là bao nhiêu. Bây giờ thay đổi code thì lại được:
Mã:
Sub test2()
    If ThisWorkbook.Sheets(1).Range("C3").Font.Color = RGB(0, 176, 240) Then MsgBox "OK"
End Sub
Vấn đề là tại sao cái số -1003520 kia lại tương đương với RGB(0,176,240). Tại sao tôi lại tính ra được RGB? Và nếu không nhầm thì RGB là hàm luôn trả về là một số dương. Vậy thì tại sao lại có số âm ở đây? Và tất nhiên tôi cũng không đủ tinh mắt để nhìn vào bảng màu RGB rồi tra cứu. Cách tính như thế nào? Các bạn đã biết chưa?
 

Euler

Administrator
Thành viên BQT
Lệnh tô màu:
Bạn cần đăng nhập để thấy hình ảnh

Bạn cần đăng nhập để thấy hình ảnh

Đối với Excel 2003 ta có code như sau:
Mã:
Sub Macro1()
    Selection.Font.ColorIndex = 3
End Sub
Các bạn có thể kiểm chứng bằng chức năng ghi code macro.
Với Excel2007 trở đi thì code sẽ dưới dạng như sau:
Mã:
Sub Macro1()
    Selection.Font.Color = -16776961 'Tô màu
    Selection.Font.TintAndShade = 0 'Độ sáng tối, có giá trị từ -1,0,1
End Sub
Thuộc tính bây giờ không còn là ColorIndex mà là Color.
Vậy số -16776961 này là gì?
Excel 2003 trở về trước, nó chỉ dùng 56 màu cơ bản. Việc ghi macro và nhận mã màu rồi sử dụng chẳng có vấn đề gì xảy ra. Cho tới khi lên tới Excel 2007, chính xác là công ty nâng cấp lên Excel cao hơn, và mình thấy dùng lệnh ghi mã màu cứ chệch choạc làm sao ấy.
Thuộc tính Color dùng hàm RGB để thiết định màu.
Giá trị trả về của hàm RGB là kiểu Long Long, là 8 byte.
RGB(red, green, blue)
red:RGB R(đỏ):0~255
green:RGB G(xanh lục):0~255
blue:RGB B(xanh da trời):0~255
Như vậy hàm RGB gồm ba tham số như đã nói ở trên, nó là sự pha trộn của ba màu.
Bạn cần đăng nhập để thấy hình ảnh


Nếu ta cho tham số đỏ=255, xanh lục =0, xanh da trời =0 ta có RGB(255,0,0) sẽ cho ra màu đỏ.
Và công thức tính của nó là RGB = R + G*256 + B*256*256
Bạn hãy thử chạy đoạn code sau:
Mã:
Sub Sample1()
    MsgBox RGB(112, 48, 160)
End Sub
Kết quả sẽ là:
Bạn cần đăng nhập để thấy hình ảnh


Mỗi màu cơ bản sử dụng 8 bit (0~255) tức là 1 byte, tương ứng 256 trạng thái với độ đậm nhạt khác nhau.
Như vậy hàm RGB với sự tổng hợp của ba màu cơ bản, mỗi màu có 256 trạng thái, sẽ cho ra 256*256*256 = 167772016 màu, hơn 16 triệu màu.
Ta thử chạy đoạn code sau:
Mã:
Sub Sample2()
    Dim i As Long, j As Long
    For i = 0 To 255 Step 5
        j = j + 1
        Cells(j, 1).Interior.Color = RGB(i, 0, 0)
        Cells(j, 1) = i & ", 0, 0"
        Cells(j, 2).Interior.Color = RGB(255, i, 0)
        Cells(j, 2) = "255, " & i & ", 0"
        Cells(j, 3).Interior.Color = RGB(0, 255, i)
        Cells(j, 3) = "0, 255, " & i
    Next i
End Sub
Kết quả trên Excel 2003 là:
Bạn cần đăng nhập để thấy hình ảnh


Kết quả trên Excel 2007:
Bạn cần đăng nhập để thấy hình ảnh


Vậy thì -16776961 là gì? Không phải hàm RGB sẽ cho ra số nguyên dương như ở trên đã nói hay sao?
Việc Excel tự ý thay đổi số liệu khiến cho chúng ta không hiểu đâu là vấn đề.
 

tuhocvba

Administrator
Thành viên BQT
Vấn đề nó nằm ở chỗ này:
If Cells(i, 6).Font.Color = -1003520
Hàm RGB sẽ cho ra một số nguyên dương, nếu dùng số nguyên dương hoặc ghi thẳng vào đó là RGB thì Excel sẽ hiểu ngay. Nhưng bê một số âm vào đó thì mình phải hiểu số âm ấy là gì, riêng Excel thì nó không hiểu mặc dù tự nó sinh ra được con số ấy.
Trong video này mình sẽ giải thích vấn đề trên, tại sao và tại sao.
Bạn cần đăng nhập để thấy đa phương tiện
Nguồn tham khảo:
 

hocchobiet

Yêu THVBA
Chào mọi người. Mn cho mình hỏi câu lệnh này nghĩa là gì ạ? có thể giải thích cho mình ý nghĩa của các thành phần trong đó đc k ạ. Mình xin cảm ơn!
Selection.Range(Cell(1,1), Cells(1,5).interior.color=RGB (204,255,153)
 

tuhocvba

Administrator
Thành viên BQT
Chào @hocchobiet
Câu lệnh của bạn sai, tôi không biết bạn copy ở đâu ra.
Hoặc là:
Selection.interior.color=RGB (204,255,153)
selection là vùng mà bạn đang select. Ví dụ bạn đang select vùng range: A1 : C3
Như thế khi viết selection, nó có nghĩa ám chỉ đang làm việc với A1: C3
Các phần sau là lệnh tô màu cho vùng Range ấy.
Chỉ định màu bằng hàm RGB đã giải thích trên diễn đàn, bạn có thể tìm kiếm hoặc tự google.

Hoặc là:
Range(Cell(1,1), Cells(1,5)).interior.color = RGB (204,255,153)
Thay vì mơ hồ Selection , thì ở dòng code này chỉ định rõ ràng là chúng ta sẽ tô màu vùng Range: A1 : A5.
 

NhanSu

SMod
Thành viên BQT
Ví dụ Selection là các ô B1:E2.Khi đó Selection.Range("A1") hoặc Selection.cells(1,1) đều trỏ đến ô B1 là ô trên bên trái của vùng chứ không phải ô A1 trên sheet. Tương tự, selection.range(range("c3"),range("d4")) hay selection.range(cells(3,3),cells(4,4)) sẽ tương ứng với vùng D3:E4 trên sheet.
Nếu selection bao gồm nhiều vùng (ví dụ B1:C2, C1:H1, A1:C3) thì selection.range sẽ lấy vị trí tương đối so với ô trên trái của vùng thứ nhất (tức là ô so sánh với B1)
Đối với câu hỏi của bạn đang thiếu dấu ")", nếu selection đang là B2:C3 chẳng hạn thì vùng tô màu sẽ là B2:F2
 
Sửa lần cuối:
Top