Nội dung trong file không đọc được khi dùng FSO.OpenTextFile và .WriteLine

Liên hệ QC

duyamadet

Thành viên mới
Tham gia
16/3/07
Bài viết
24
Được thích
3
Chào các bác,
1) Nhờ các bác xem file đính kèm và giúp em cách khắc phục khi ở file txt và ghi thêm nội dung vào và lưu lại.
Em dùng FSO.OpenTextFile và WriteLine:
- Lần đầu tiên sẽ tạo file mới và ghi dữ liệu bình thường
- Lần chạy thứ 2 trở đi, sẽ hiện ra tiếng tàu
(Report.xlsm chứa macro; Data.txt là file output do Report tạo ra)

2) Ví dụ file txt đang có người khác đọc (file txt lưu ở ổ đĩa Share) thì lệnh ở 1) có thể lưu tiếp dữ liệu mới được không? hay báo lỗi ReadOnly? Và cách khắc phục trong trường hợp Readonly này? (em định là Save as tên mới)

3) FSO chỉ có thể OpenTextFile thôi phải không? (không mở file excel ví dụ OpenExcelFile)?
Ví dụ muốn copy dữ liệu vào file excel thì phải mở file đó lên và copy paste bình thường phải không?

Em cảm ơn các bác.
 

File đính kèm

  • Report.xlsm
    17.7 KB · Đọc: 3
  • Data.txt
    190 bytes · Đọc: 4
Chào các bác,
1) Nhờ các bác xem file đính kèm và giúp em cách khắc phục khi ở file txt và ghi thêm nội dung vào và lưu lại.
Em dùng FSO.OpenTextFile và WriteLine:
- Lần đầu tiên sẽ tạo file mới và ghi dữ liệu bình thường
- Lần chạy thứ 2 trở đi, sẽ hiện ra tiếng tàu
(Report.xlsm chứa macro; Data.txt là file output do Report tạo ra)
1. Lần đầu bạn có Set MyFile = FSO.createTextFile(pPath, False, True).

True có nghĩa là tạo tập tin Unicode.

2. Lần 2 bạn có Set MyFile = FS. Opentextfile(pPath, 8, True)

Function OpenTextFile(FileName As String, [IOMode As IOMode = ForReading], [Create As Boolean = False], [Format As Tristate = TristateFalse]) As TextStream

True ở trên là Create = True (tham số thứ 3). Như vậy tham số thứ 4 vẫn là mặc định tức Format = TristateFalse, tức tập tin được mở với TƯ CÁCH là tập tin ASCII. Vì thế mới có "đầu trâu mặt ngựa".

Muốn mở tập tin với TƯ CÁCH là Unicode thì phải có Format = TristateTrue = -1.

Tóm lại phải có:
Set MyFile = FS. Opentextfile(pPath, 8, True, True)
-----------
Nếu muốn tạo tập tin mới khi chưa có, và mở khi đã có thì không cần CreateTextFile, vì OpenTextFile có tham số Create để xác định tạo mới hay mở. Vậy code rút gọn chỉ là
Mã:
Sub RecordData()
Dim fso, ts As Object
Dim pPath As String, FileName As String, s As String
    Set fso = CreateObject("Scripting.FileSystemObject")
    pPath = "C:\ABC\"
    If Not fso.FolderExists(pPath) Then fso.CreateFolder (pPath)
  
    pPath =  "C:\ABC\Data.txt"
    On Error Resume Next
    Set ts = fso.OpenTextFile(pPath, 8, True, -1)   ' Create = True có nghĩa là tạo mới khi chưa có, và mở khi đã có
    If Err.Number = 0 Then
        ts.WriteLine "Hello World!" & vbTab & Format(Time, "hh:mm:ss")
        ts.WriteLine "Hello People!" & vbTab & Format(Time, "hh:mm:ss")
        ts.Close
        Set ts = Nothing
    End If
'    On Error GoTo 0
    Set fso = Nothing
End Sub

2) Ví dụ file txt đang có người khác đọc (file txt lưu ở ổ đĩa Share) thì lệnh ở 1) có thể lưu tiếp dữ liệu mới được không? hay báo lỗi ReadOnly? Và cách khắc phục trong trường hợp Readonly này? (em định là Save as tên mới)
Code ở trên đã xử lý trường hợp bạn nói. Tức nếu vì một lý do nào đó sảy ra lỗi thì code trên đã xừ lý. Vd. trước đó người dùng vì nhu cầu nào đó mà tự mở Data.txt trong Excel rồi chưa đóng nó mà chạy code thì sẽ có lỗi. Nhưng code trên xử lý lỗi do dùng On Error Resume Next nên bạn không thấy báo lỗi.

3) FSO chỉ có thể OpenTextFile thôi phải không? (không mở file excel ví dụ OpenExcelFile)?
Ví dụ muốn copy dữ liệu vào file excel thì phải mở file đó lên và copy paste bình thường phải không?
Rõ ràng tên hàm OpenTextFile có chứa TEXT nên nó chỉ mở tập tin TXT thôi. Tập tin Excel có cấu trúc khác. Nếu cố tình mở tập tin vd. XLSX thì cũng được thôi nhưng nếu đọc (read) thì sẽ nhận được "đầu trâu mặt ngựa".

Tên hàm trong lập trình chứa rất nhiều thông tin. Nhiều khi nhìn tên hàm là đã biết gần 50% nó là gì, làm gì ...
 
Upvote 0
Cảm ơn anh Batman1 rất nhiều.
Cho em hỏi thêm về mục số 2.
Em cần lưu dữ liệu mới tiếp tục vào file, nối tiếp dữ liệu đang có, dù có người đang mở file thì vẫn ghi tiếp tục dữ liệu mới.
- Em test thử, dùng file txt đang mở, chạy code trên, code vẫn tiếp tục ghi dữ liệu mới vào file và dữ liệu mới được lưu. Nhưng nếu trở lại file đang mở, em nhấn Ctrl S thì dữ liệu mới sẽ bị mất (trở về dữ liệu tại thời điểm mở file lên để đó).
- Em định khắc phục bằng cách SetAttr vbNormal trước khi ghi dữ liệu mới vào file, ghi xong SetAttr vbReadOnly, nhưng không thành công. Dù em cố tình cài property cho file đó bằng tay là Readonly+Hidden thì sau khi chạy code vẫn trở về dạng bình thường (không ReadOnly, không Hidden).

Anh Batman1 và các anh chị khác chỉ giúp em code đúng để SetAttr có tác dụng (vbReadOnly + vbHidden).
Hoặc anh chị có cách nào khác hay hơn (tiếp tục ghi dữ liệu mới mặc cho file đang được mở).

Cảm ơn anh chị nhiều.

Mã:
Sub RecordData()
Dim fso, ts As Object
Dim pPath As String, FileName As String, s As String
    Set fso = CreateObject("Scripting.FileSystemObject")
    pPath = "C:\ABC\"
    If Not fso.FolderExists(pPath) Then fso.CreateFolder (pPath)
 
    pPath = "C:\ABC\Data.txt"
    On Error Resume Next
    SetAttr "C:\ABC\Data.txt", vbNormal        '<--Them cau nay'
    Set ts = fso.OpenTextFile(pPath, 8, True, -1)   ' Create = True co´ nghi~a la` ta?o mo´i khi chua co´, va` mo? khi da~ co´
    If Err.Number = 0 Then
        ts.WriteLine "Hello World!" & vbTab & Format(Time, "hh:mm:ss")
        ts.WriteLine "Hello People!" & vbTab & Format(Time, "hh:mm:ss")
        ts.Close
        SetAttr "C:\ABC\Data.txt", vbReadOnly + vbHidden    <--Them cau nay
        Set ts = Nothing
    End If
'    On Error GoTo 0
    Set fso = Nothing
    SetAttr "C:\ABC\Data.txt", vbReadOnly And vbHidden
End Sub
 
Upvote 0
Cảm ơn anh Batman1 rất nhiều.
Cho em hỏi thêm về mục số 2.
Em cần lưu dữ liệu mới tiếp tục vào file, nối tiếp dữ liệu đang có, dù có người đang mở file thì vẫn ghi tiếp tục dữ liệu mới.
- Em test thử, dùng file txt đang mở, chạy code trên, code vẫn tiếp tục ghi dữ liệu mới vào file và dữ liệu mới được lưu. Nhưng nếu trở lại file đang mở, em nhấn Ctrl S thì dữ liệu mới sẽ bị mất (trở về dữ liệu tại thời điểm mở file lên để đó).
- Em định khắc phục bằng cách SetAttr vbNormal trước khi ghi dữ liệu mới vào file, ghi xong SetAttr vbReadOnly, nhưng không thành công. Dù em cố tình cài property cho file đó bằng tay là Readonly+Hidden thì sau khi chạy code vẫn trở về dạng bình thường (không ReadOnly, không Hidden).

Anh Batman1 và các anh chị khác chỉ giúp em code đúng để SetAttr có tác dụng (vbReadOnly + vbHidden).
Hoặc anh chị có cách nào khác hay hơn (tiếp tục ghi dữ liệu mới mặc cho file đang được mở).

Cảm ơn anh chị nhiều.

Mã:
Sub RecordData()
Dim fso, ts As Object
Dim pPath As String, FileName As String, s As String
    Set fso = CreateObject("Scripting.FileSystemObject")
    pPath = "C:\ABC\"
    If Not fso.FolderExists(pPath) Then fso.CreateFolder (pPath)
 
    pPath = "C:\ABC\Data.txt"
    On Error Resume Next
    SetAttr "C:\ABC\Data.txt", vbNormal        '<--Them cau nay'
    Set ts = fso.OpenTextFile(pPath, 8, True, -1)   ' Create = True co´ nghi~a la` ta?o mo´i khi chua co´, va` mo? khi da~ co´
    If Err.Number = 0 Then
        ts.WriteLine "Hello World!" & vbTab & Format(Time, "hh:mm:ss")
        ts.WriteLine "Hello People!" & vbTab & Format(Time, "hh:mm:ss")
        ts.Close
        SetAttr "C:\ABC\Data.txt", vbReadOnly + vbHidden    <--Them cau nay
        Set ts = Nothing
    End If
'    On Error GoTo 0
    Set fso = Nothing
    SetAttr "C:\ABC\Data.txt", vbReadOnly And vbHidden
End Sub
Tôi không có ổ đĩa Share mà cũng chả biết ổ đĩa Share là gì và nó ở đâu để test. Nhưng tôi rất khó tính.

Với tôi "dùng file txt đang mở, chạy code trên, code vẫn tiếp tục ghi dữ liệu mới vào file và dữ liệu mới được lưu" không đủ. "file txt đang mở"? Mở ở đâu? Giả sử code ở máy A. Vậy "file txt đang mở" ở đâu? Sau khi chạy code làm sao biết có dữ liệu ghi thêm? Tự vào Share mở tập tin Txt bằng tay trong notepad để kiểm tra? Thế sau khi trở lại file đang mở, và nhấn Ctrl S thì dữ liệu mới sẽ bị mất? Sao biết mất? Lại vào Share và tự mở bằng tay trong notepad tập tin txt? Chỉ nhấn Ctrl + S mà tập tin trên đĩa đang có đoạn đoạn nào đó thì tự mất đi đoạn đó? Hay là tập tin txt được mở như thế nào đấy trong Excel và khi nhấn Ctrl + S thì không có đoạn thêm nhưng trong Share thì tập tin txt vẫn có đoạn thêm? Khó hiểu.

Bạn chờ người khác nhé
 
Upvote 0
tiếp tục ghi dữ liệu mới mặc cho file đang được mở

Cái Text File của Windows rất huyền bí. Ai chuyên ghi log thì sẽ rành cái này.
Nó cho phép ghi thêm dữ liệu trong khi file đó đang được mở ở phiên làm việc khác.
Nếu dùng phần mềm mặc định của Windows là Notepad để mở thì:
- Có thể mở cùng 1 file đó lên nhiều cửa sổ (phiên làm việc) khác nhau.
- Nếu thay đổi nội dung (xóa, thêm, bớt) ở một cửa sổ làm việc nào đó thì KHÔNG CẬP NHẬT lên cửa sổ làm việc khác.
Kết quả cuối cùng trong file đó thuộc về phiên làm việc được lưu cuối cùng.

Muốn có cái bạn mong muốn: Ghi dữ liệu thêm vào text file đang mở, và được cập nhật lên cửa sổ đang mở thì PHẢI dùng trình duyệt Text File khác.
Hàng ngon nhất là Sublime Text, khi ghi thêm mới dữ liệu vào thì được cập nhật lên luôn.
Hàng ngon kế tiếp (không thơm ngon bằng Sublime Text) là Notepad++, khi thêm mới dữ liệu vào thì nó sẽ báo cho mình có cập nhật mới hay không?

1649258393138.png
 
Upvote 0
Em cảm ơn bác Batman1, code của bác đã thực hiện được đều em đang cần.
Phần sau (#3), em test lại SetAttr đã thành công rồi. Mong bác bớt giận nhé.

Em cảm ơn bác Befaint, đúng là em đang cần ghi log. Những điều bác nói giống với điều em đang muốn khắc phục (em lo 1 người nào đó mở file log ra xem trong khi file macro đang chạy thì dữ liệu mới (ghi thêm vào file log) có thể bị mất nếu người kia nhấn Ctrl S. Tạm thời em khắc phục thành công với SetAttr vbReadOnly rồi.

Cảm ơn mọi người.
 
Upvote 0
Web KT

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

Back
Top Bottom