Chính xác là nó sẽ ra FALSE đối với tất cả các code dùng Dir hoặc
FSO vì các hàm này không dùng được cho tên Folder hoặc File tiếng Việt có dấu (Non-English name).
Mọi người hiểu sai trong trường hợp của bạn minhtuan55. Mọi người cứ dựa vào cái "text" đường dẫn trong ô A1 trong Excel nên các hàm Dir, FSO đều chạy ra TRUE. Nếu nó là đường dẫn thực tế có folder là tiếng Việt và file jpg thật ngay trên máy của bạn thì nó sẽ báo FALSE ngay. Các bạn tự đổi file ảnh nào đó trên máy bạn rồi copy đường dẫn vô ô A1 đi sẽ thấy.
Lần đầu tiên trong đời nghe thấy nói là
fso không chấp nhận unicode. Dir của VBA thì đúng rồi. Nhưng fso không phục vụ unicode?
Nói là một chuyện nhưng cần đưa ra ví dụ để chứng minh.
Vấn đề không nằm ở fso. Cũng không nằm ở unicode. Nó nằm ở
sự khác biệt giữa 2 dạng unicode tham gia vào quá trình so sánh. Vấn đề là trong tiếng Việt có thể dùng unicode tổ hợp và unicode dựng sẵn. Nếu bạn khi tạo các thư mục trên đĩa bạn gõ bằng unicode dựng sẵn. Nhưng khi bạn gõ vào A1 lại dùng unicode tổ hợp thì dùng mắt bạn không thể phát hiện là 2 đường dẫn khác nhau. Nhưng chúng là khác nhau. Và lúc đó thì code vd.
Workbooks.Open <đường dẫn trong A1> chắc chắn sẽ có lỗi.
Lúc này không thể đổ tội cho Excel, VBA là không chấp nhận unicode vì nó chấp nhận, nó mở được các tập tin có đường dẫn unicode. Chỉ là phải cung cấp đường dẫn y hệt như trên đĩa. Y hệt ở đây không phải là "mặt mũi" như nhau mà là "nội dung". Cũng không thể đổ lỗi cho Dir, cho fso vì chúng không được dùng. Vậy thì đổ tội cho "ai"? Do đường dẫn trên đĩa là một dạng unicode còn nhập vào A1 lại là dạng unicode khác. Đó mới chính là nguyên nhân. Nếu muốn đổ lỗi cho fso thì phải đưa ra chứng cứ.
Tôi đính kèm ví du.
Trong tập tin có A1 = "đây là thư mục tiếng Việt nhé\Excel Hinh anh\Hinh anh\Mẫn tú\Những Mẫn.jpg".
Tại sao không có đoạn đầu? Đơn giản vì mỗi người tải tập tin của tôi về và giải nén thì sẽ có đoạn đầu của đường dẫn khác nhau. Đoạn đầu này code sẽ lấy từ ThisWorkbook.Path để thêm vào và tạo đường dẫn hoàn chỉnh.
ThisWorkbook.Path & "\" & Range("A1").Value chắc chắn tồn tại, vì A1 được tôi copy và dán bằng tay từ thanh địa chỉ của Explorer.
Code sẽ convert A1 sang unicode dựng sẵn. Tức bất luận A1 là unicode tổ hợp hay unicode dựng sẵn thì kết quả convert luôn luôn là unicode dựng sẵn. Kết quả này code sẽ nhập vào A2.
Khi chạy code test thì tôi có thông báo:
- "Tap tin A1 ton tai"
- "Tap tin A2 khong ton tai"
Điều này dễ hiểu vì tuy 2 đường dẫn nhìn như nhau nhưng "lõi" khác nhau. Len(A1) = 79. Len(A2) = 74.
Nếu bạn cho là fso không phục vụ unicode thì hãy đưa ra ví dụ cho người khác kiểm tra.
Nguyên nhân không nằm ở fso. Nguyên nhân ở chỗ là trong tiếng Việt có thể dùng unicode tổ hợp và dựng sẵn. Vì thế 2 đoạn text là y hệt nhau về mặt văn bản nhưng có thể khác nhau khi ghi trên đĩa, vd. trong tập tin TXT, khi dùng trong vd. Excel. Vì VBA không nhìn bằng "mắt" mà nó "cân đo đong đếm" nội dung, "lõi".
Cũng có thể khắc phục trường hợp khi đường dẫn trên đĩa và đường dẫn cần kiểm tra là 2 loại unicode khác nhau, nhưng code không ngắn gọn được. Có thể có nhiều ý tưởng. Nếu là tôi thì cho tới khi nghĩ ra cái hay hơn thì tôi sẽ dùng thuật toán như sau:
0. Code convert A1 sang unicode dựng sẵn -> ghi kết quả vào biến A1dungsan.
1. Code sẽ xác định thư mục cuối cùng trong đường dẫn A1 mà đoạn đầu tới nó chỉ chứa ký tự ANSI. Trong tập tin vd. thì đó là thư mục mà con của nó là thư mục "đây là thư mục tiếng Việt nhé". Ta gọi đó là startDir. Vd. startDir = "C:\Users\Administrator\Desktop\Excel Hinh anh\Hinh anh" (đường dẫn tới ảnh là "C:\Users\Administrator\Desktop\Excel Hinh anh\Hinh anh\đây là thư mục tiếng Việt nhé\Excel Hinh anh\Hinh anh\Mẫn tú\Những Mẫn.jpg")
2. Code sẽ tìm và liệt kê tất cả các tập tin có trong startDir và các thư mục con, vd. nhập vào listFiles. Mục đích của điểm 1 để listFiles ngắn nhất. Bởi nếu tìm trong "C:\", trong "C:\Users", trong "C:\Users\Administrator" ... thì listFiles sẽ dài. Mà thực ra ta chỉ cần các tập tin trong startDir, vì các tập tin vd. trong "C:\Users\Administrator" thì đâu cần quan tâm.
3. Code sẽ duyệt từng đường dẫn trong listFiles -> convert sang unicode dựng sẵn -> so sánh với A1dungsan. Nếu kết quả là bằng nhau thì hàm trả về TRUE và đồng thời ghi vào B1 giá trị của đường dẫn đang xét lấy từ listFiles (tức dạng đường dẫn trên đĩa). Hoặc ghi đường dẫn thực trên đĩa vào tham số được truyền bởi ByRef. Và code kết thúc.
Nếu code duyệt hết listFiles (vòng FOR) mà không có kết quả so sánh nào bằng nhau thì dĩ nhiên là đường dẫn không tồn tại.