Giúp File Đọc Số ra Âm thanh dùng trong Khu Cách Ly COVID-19 (7 người xem)

Liên hệ QC

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

  • hunglam123

    Thành viên bị đình chỉ hoạt động
    Thành viên bị đình chỉ hoạt động
    Tham gia
    31/3/20
    Bài viết
    180
    Được thích
    43
    Em xin chào cả nhà. Hiện tại bên công ty đã đều em đến 1 trung tâm quản lý các bệnh nhân cách ly tại Quận 9 ( Em làm bên nghành y tế ) . hằng ngày cứ 3 lần em đều thấy mấy anh Quân Nhân phải đọc số để Đo nhiệt độ và phát cơm mổi ngày. Nên em nghỉ ra ý tưởng lập 1 file excel để khi nhập số vào nhấn nút đọc thì âm thanh từ máy tính sẽ phát ra Loa bên ngoài. để mọi người như đều nghe thấy
    Giao diện như thế này


    Vùng B4:B15 là vùng lấy đường dẫn File âm thanh. Tức nhiên em đã thu âm các số 0,1,2,3..9 và câu mở đầu và câu kết thúc
    Tại ô F4 em muốn nhập số bệnh nhân vào
    Tại ô G4 em nhập số lần lặp lại
    Nhấn nút Đọc số thì chương trình đọc ra âm thanh.
    Ví dụ gõ số 0123 thì Loa phát ra " Xin mời quý khách mang số . không Một Hai Ba . Vui lòng đến quầy "

    Do kiến thức em hạn hẹp em chỉ tạo mỗi được giao diện , và em đã thu âm và đã đổi sang đươi WAV hết, và các câu lệnh lấy đường dẫn âm thanh. Phần đọc số em chưa biết dùng câu lệnh gì.
    rất mong mọi người cùng cac bang Quản Trị Viên giúp đở để chương trình đưa ra hoạt động giúp đở cộng đồng vướt qua mùa dịch này. Một lần nữa em xin chân thành cảm ơn
     
    Lần chỉnh sửa cuối:
    Đơn giản nhất là dùng hàm API PlaySound.

    1. Thay các tập tin WMA bằng các tập tin WAV.

    2. Thêm Module với code sau
    Mã:
    Option Explicit
    
    Private Const SND_FILENAME As Long = &H20000
    Private Const SND_SYNC As Long = &H0
    
    #If VBA7 Then
        Private Declare PtrSafe Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As LongPtr, ByVal dwFlags As Long) As Long
    #Else
        Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long
    #End If
    
    Sub RoundedRectangle2_Click()
    Dim k As Long, n As Long, lap As Long, so As String
        so = Range("F4").Value
        lap = Range("G4").Value
        For n = 1 To lap
            PlaySound ThisWorkbook.Path & "\am thanh\Cau mo dau.wav", 0, SND_FILENAME Or SND_SYNC
            For k = 1 To Len(so)
                PlaySound ThisWorkbook.Path & "\am thanh\so " & Mid(so, k, 1) & ".wav", 0, SND_FILENAME Or SND_SYNC
            Next k
            PlaySound ThisWorkbook.Path & "\am thanh\Vui long den quay.wav", 0, SND_FILENAME Or SND_SYNC
            Application.Wait Now + TimeValue("0:00:02")
        Next n
    End Sub

    3. Gán cho nút "ĐỌC SỐ" macro RoundedRectangle2_Click
     
    Upvote 0
    Đơn giản nhất là dùng hàm API PlaySound.

    1. Thay các tập tin WMA bằng các tập tin WAV.

    2. Thêm Module với code sau
    Mã:
    Option Explicit
    
    Private Const SND_FILENAME As Long = &H20000
    Private Const SND_SYNC As Long = &H0
    
    #If VBA7 Then
        Private Declare PtrSafe Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As LongPtr, ByVal dwFlags As Long) As Long
    #Else
        Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long
    #End If
    
    Sub RoundedRectangle2_Click()
    Dim k As Long, n As Long, lap As Long, so As String
        so = Range("F4").Value
        lap = Range("G4").Value
        For n = 1 To lap
            PlaySound ThisWorkbook.Path & "\am thanh\Cau mo dau.wav", 0, SND_FILENAME Or SND_SYNC
            For k = 1 To Len(so)
                PlaySound ThisWorkbook.Path & "\am thanh\so " & Mid(so, k, 1) & ".wav", 0, SND_FILENAME Or SND_SYNC
            Next k
            PlaySound ThisWorkbook.Path & "\am thanh\Vui long den quay.wav", 0, SND_FILENAME Or SND_SYNC
            Application.Wait Now + TimeValue("0:00:02")
        Next n
    End Sub

    3. Gán cho nút "ĐỌC SỐ" macro RoundedRectangle2_Click
    Dạ em cảm ơn thầy ạ Hay quá thầy ơi. Chiều này em gắn a6mly cho phát ra Loa luôn
     
    Upvote 0
    Đơn giản nhất là dùng hàm API PlaySound.

    1. Thay các tập tin WMA bằng các tập tin WAV.

    2. Thêm Module với code sau
    Mã:
    Option Explicit
    
    Private Const SND_FILENAME As Long = &H20000
    Private Const SND_SYNC As Long = &H0
    
    #If VBA7 Then
        Private Declare PtrSafe Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As LongPtr, ByVal dwFlags As Long) As Long
    #Else
        Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long
    #End If
    
    Sub RoundedRectangle2_Click()
    Dim k As Long, n As Long, lap As Long, so As String
        so = Range("F4").Value
        lap = Range("G4").Value
        For n = 1 To lap
            PlaySound ThisWorkbook.Path & "\am thanh\Cau mo dau.wav", 0, SND_FILENAME Or SND_SYNC
            For k = 1 To Len(so)
                PlaySound ThisWorkbook.Path & "\am thanh\so " & Mid(so, k, 1) & ".wav", 0, SND_FILENAME Or SND_SYNC
            Next k
            PlaySound ThisWorkbook.Path & "\am thanh\Vui long den quay.wav", 0, SND_FILENAME Or SND_SYNC
            Application.Wait Now + TimeValue("0:00:02")
        Next n
    End Sub

    3. Gán cho nút "ĐỌC SỐ" macro RoundedRectangle2_Click
    Thầy ơi thầy có thể sửa lại code để em lấy Địa chỉ từ Đường dẩn được không. tại sau này em đổi tên File âm thanh lại file đổi lại trong code nữa. Mong thầy sửa lại code lấy từ Vùng Đường dẫn để cho sau này em thay đổi tên thì em chỉ cần chọn lại đường dẫn là được

    PlaySound ThisWorkbook.Path & "\am thanh\Cau mo dau.wav", 0, SND_FILENAME Or SND_SYNC

    "\am thanh\Cau mo dau.wav",
    Đoạn này em muốn nó lấy từ đường dẫn
     
    Upvote 0
    Thầy ơi thầy có thể sửa lại code để em lấy Địa chỉ từ Đường dẩn được không. tại sau này em đổi tên File âm thanh lại file đổi lại trong code nữa. Mong thầy sửa lại code lấy từ Vùng Đường dẫn để cho sau này em thay đổi tên thì em chỉ cần chọn lại đường dẫn là được

    PlaySound ThisWorkbook.Path & "\am thanh\Cau mo dau.wav", 0, SND_FILENAME Or SND_SYNC

    "\am thanh\Cau mo dau.wav",
    Đoạn này em muốn nó lấy từ đường dẫn
    Tôi không hiểu ý bạn lắm. Hiện tại trong cùng 1 thư mục nào đó có tập tin Excel và thư mục con "am thanh". Và trong thư mục "am thanh" có các tập tin WAV. Ý bạn là thư mục có WAV không luôn luôn có tên là "am thanh", và nó không luôn luôn nằm cùng thư mục với tập tin Excel? Nếu thế thì nhập đường dẫn tới thư mục có WAV vào vd. A2. Ví dụ nhập A2 = D:\nhac cua toi\wav ua thich\covid-19

    Mã:
    Sub RoundedRectangle2_Click()
    Dim k As Long, n As Long, lap As Long, so As String, folder As String
        so = Range("F4").Value
        lap = Range("G4").Value
        folder = Range("A2").Value
        For n = 1 To lap
            PlaySound folder & "\Cau mo dau.wav", 0, SND_FILENAME Or SND_SYNC
            For k = 1 To Len(so)
                PlaySound folder & "\so " & Mid(so, k, 1) & ".wav", 0, SND_FILENAME Or SND_SYNC
            Next k
            PlaySound folder & "\Vui long den quay.wav", 0, SND_FILENAME Or SND_SYNC
            Application.Wait Now + TimeValue("0:00:02")
        Next n
    End Sub
     
    Upvote 0
    Tôi không hiểu ý bạn lắm. Hiện tại trong cùng 1 thư mục nào đó có tập tin Excel và thư mục con "am thanh". Và trong thư mục "am thanh" có các tập tin WAV. Ý bạn là thư mục có WAV không luôn luôn có tên là "am thanh", và nó không luôn luôn nằm cùng thư mục với tập tin Excel? Nếu thế thì nhập đường dẫn tới thư mục có WAV vào vd. A2. Ví dụ nhập A2 = D:\nhac cua toi\wav ua thich\covid-19

    Mã:
    Sub RoundedRectangle2_Click()
    Dim k As Long, n As Long, lap As Long, so As String, folder As String
        so = Range("F4").Value
        lap = Range("G4").Value
        folder = Range("A2").Value
        For n = 1 To lap
            PlaySound folder & "\Cau mo dau.wav", 0, SND_FILENAME Or SND_SYNC
            For k = 1 To Len(so)
                PlaySound folder & "\so " & Mid(so, k, 1) & ".wav", 0, SND_FILENAME Or SND_SYNC
            Next k
            PlaySound folder & "\Vui long den quay.wav", 0, SND_FILENAME Or SND_SYNC
            Application.Wait Now + TimeValue("0:00:02")
        Next n
    End Sub

    ý em là sao thầy không lấy đường dẫn từ vùng B4:B15 vào Code mà lại đặt luôn tên âm thanh vào code
    Ví dụ chỗ này
    PlaySound ThisWorkbook.Path & "\am thanh\Cau mo dau.wav", 0, SND_FILENAME Or SND_SYNC

    Thì làm sao thầy lấy từ ô B14 luôn
    PlaySound ThisWorkbook.Path & Range("b14"), 0, SND_FILENAME Or SND_SYNC

    Để sau này File âm thanh có đổi tên thì em chỉ chọn sửa lại tên đường dẫn tại ô B14 khỏi cần sữa lại tên trong code. ý em là vậy đó

    Tương tự như Chổ này
    PlaySound ThisWorkbook.Path & "\am thanh\so " & Mid(so, k, 1) & ".wav", 0, SND_FILENAME Or SND_SYNC

    Thì làm sao để nó đường dẫn từ Vùng B4:B13
    Tại vì để tránh trường hợp sau này thư mục âm thanh em để không chung thư mục của file excel này ạ
     
    Upvote 0
    ý em là sao thầy không lấy đường dẫn từ vùng B4:B15 vào Code mà lại đặt luôn tên âm thanh vào code
    Ví dụ chỗ này
    PlaySound ThisWorkbook.Path & "\am thanh\Cau mo dau.wav", 0, SND_FILENAME Or SND_SYNC
    Tôi trả lời trong vấn đề cụ thể. Bạn có 12 tập tin, trong đó có 10 tập tin số: "so 1", ..., "so 9". Bạn đổi tên làm gì? "Day la cau mo dau ua thich cua tôi.wav" tốt hơn "Cau mo dau.wav" chăng? Lý do đặt thư mục có WAV ở chỗ khác là lý do chính đáng. Lý do đổi tên "am thanh" cũng là lý do chính đáng. Vì bạn có thể có 1 thư mục "Wav" mà trong đó có nhiều thư mục con: SARS-2002, COVID-19 ... Vì lẽ đó tôi đề nghị nhập đường dẫn thư mục vào A2. Còn tên thì thế nào chả được, sao phải đổi tên? Đổi thành "Day la cau mo dau ua thich cua tôi.wav" thì âm thanh sẽ chuẩn hơn hay sao?

    Nếu bạn muốn theo ý mình thì đọc ra các ô trong cột B thôi. Cách đọc thì bạn biết rồi, mà tôi cũng có trong code cách đọc, so, folder và lay. Cứ bắt chước thôi.
    Tại vì để tránh trường hợp sau này thư mục âm thanh em để không chung thư mục của file excel này ạ
    Thì tôi đã viết là trong trường hợp để thư mục âm thanh ở chỗ khác thì nhập đường dẫn tới thư mục vào A2 rồi còn gì. Bạn đã đọc chưa?
     
    Upvote 0
    Nếu máy tính có kết nối Internet thì sử dụng Google đọc (Click vào link để thử):

    http://translate.google.com/translate_tts?ie=utf-8&client=tw-ob&tl=vi&q=Xin mời quý khách mang số 0123 Vui lòng đến quầy





    Copy code dưới vào Code của Worksheet, và thử điền dữ liệu vào ô B3
    Nếu Chrome được cài đặt ở đường dẫn thì:
    C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
    Nếu Chrome hoặc Cốc Cốc hoặc Edge là Browser mặc định:
    Explorer.exe


    --------------------------
    PHP:
    Private Sub Worksheet_Change(ByVal Target As Range)
      If Target.Address(0, 0) = "B3" And VBA.IsNumeric(Target(1, 1).Value) Then
        Const Language = "vi" ' Anh = "en", Trung ="zh-cn", Nga= "ru" , ... 
    Dim P As String
        P = """C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"" ""http://translate.google.com/translate_tts?ie=utf-8&client=tw-ob&tl=" & Language &"&q="
        Shell P & "Xin%20m%E1%BB%9Di%20qu%C3%BD%20kh%C3%A1ch%20mang%20s%E1%BB%91%20..." _
        & Target.Value & "...%20Vui%20l%C3%B2ng%20%C4%91%E1%BA%BFn%20qu%E1%BA%A7y""", 0
      End If
    End Sub
     
    Lần chỉnh sửa cuối:
    Upvote 0
    Tôi trả lời trong vấn đề cụ thể. Bạn có 12 tập tin, trong đó có 10 tập tin số: "so 1", ..., "so 9". Bạn đổi tên làm gì? "Day la cau mo dau ua thich cua tôi.wav" tốt hơn "Cau mo dau.wav" chăng? Lý do đặt thư mục có WAV ở chỗ khác là lý do chính đáng. Lý do đổi tên "am thanh" cũng là lý do chính đáng. Vì bạn có thể có 1 thư mục "Wav" mà trong đó có nhiều thư mục con: SARS-2002, COVID-19 ... Vì lẽ đó tôi đề nghị nhập đường dẫn thư mục vào A2. Còn tên thì thế nào chả được, sao phải đổi tên? Đổi thành "Day la cau mo dau ua thich cua tôi.wav" thì âm thanh sẽ chuẩn hơn hay sao?

    Nếu bạn muốn theo ý mình thì đọc ra các ô trong cột B thôi. Cách đọc thì bạn biết rồi, mà tôi cũng có trong code cách đọc, so, folder và lay. Cứ bắt chước thôi.

    Thì tôi đã viết là trong trường hợp để thư mục âm thanh ở chỗ khác thì nhập đường dẫn tới thư mục vào A2 rồi còn gì. Bạn đã đọc chưa?

    Em xữ lý được rồi Thầy Ạ. Em cảm ơn thầy nhiều. tới giờ em đi Đo nhiệt độ rồi , em cảm ơn thầy ạ
     
    Lần chỉnh sửa cuối:
    Upvote 0

    File đính kèm

    Upvote 0
    -------------------------------------


    Bạn tải file sau về sử dụng cho đơn giản.


    -------------------------------------
    Báo lỗi khi mở file.
    Hinh.jpg
    Tôi thấy code một mâm vậy nghiên cứu mệt à nghe! Nếu để học hỏi thì xem code của @batman1 ở #5 sẽ hay hơn.
    Tôi thấy ở #8 cũng hay, nhưng làm sau để không hiện của sổ Chrome nửa thì tốt hơn. Vã lại làm thế nào mà mình cú được những dòng chữ màu đỏ kia.
     
    Upvote 0
    Báo lỗi khi mở file.
    Tôi thấy code một mâm vậy nghiên cứu mệt à nghe! Nếu để học hỏi thì xem code của @batman1 ở #5 sẽ hay hơn.
    Tôi thấy ở #8 cũng hay, nhưng làm sau để không hiện của sổ Chrome nửa thì tốt hơn. Vã lại làm thế nào mà mình cú được những dòng chữ màu đỏ kia.
    ------------------------

    Cái này do lỗi biên dịch VBE 7.0 trở về trước. Bác có thể tải lại file.


    Để được dòng màu đỏ sử dụng hàm EncodeURL
    Hàm EncodeURL chỉ hỗ trợ từ Office 2013 trở về sau.
    Có thể tham khảo EncodeURL trên mạng hoặc tự viết

    Còn Google Speech thì cũng viết ứng dụng rồi, Ứng dụng này nằm trong bộ ứng dụng Google Translate đang viết cho Excel chưa được hoàn thiện.
    Sau khi ứng dụng hoàn thiện chắc cũng sớm chia sẻ.



    code của bác batman1 sử dụng hàm PlaySound trong thư viện MCI Audio, nó là hàm đơn giản nhất, nhanh nhất để mở một file âm thanh.
    và PlaySound chỉ hỗ trợ mở wav (WaveAudio) mà thôi.

    với các thư viện chính trong MCI là "muôn trùng, điệp điệp", chỉ hơn 1900 trang hướng dẫn.
     
    Lần chỉnh sửa cuối:
    Upvote 0
    code của bác batman1 sử dụng hàm PlaySound trong thư viện MCI Audio, nó là hàm đơn giản nhất, nhanh nhất để mở một file âm thanh.
    và PlaySound chỉ hỗ trợ mở wav (WaveAudio) mà thôi.

    với các thư viện chính trong MCI là "muôn trùng, điệp điệp", chỉ hơn 1900 trang hướng dẫn.
    Tôi đã viết rõ là đơn giản nhất là dùng PlaySound. Và đổi WMA thành WAV vì PlaySound không phục vụ WMA.

    Còn máy vạn năng thì là mciSendString rồi.

    Về mciSendString tôi cũng đã viết hơn 7,5 năm rồi.

    ------------
    Về bài #8 thì sao lại khởi động chrome? Thứ nhất là khởi động trình duyệt sẽ lâu, thứ 2 là không phải ai cũng dùng chrome. Tôi trước kia dùng IE, bây giờ dùng Firefox. Chưa bao giờ dùng trình duyệt nào khác.

    Trong tập tin đính kèm tôi không khởi động trình duyệt nào cả.

    Tôi cũng tự viết hàm utf8_encode.

    google text to speech rất giỏi, nhưng nhiều khi dịch vẫn không chuẩn, nhiều khi dịch rất buồn cười. Nhưng cho nhu cầu chủ đề này hoàn toàn được.

    Những ai chưa biết cách lấy tập tin mp3 của google về máy thì xem tôi "biểu diễn" trong tập tin. :D
    -------
    Lưu ý.
    Có lẽ tốt hơn là các bạn sửa
    Mã:
    strUrl = ...
    thành
    Mã:
    strUrl = "https://translate.google.com/translate_tts?ie=utf-8&client=tw-ob&tl=" & lang & "&q=" & TextToUTF8(text)
    Sau đó xóa hàm utf8_encode và thêm code
    Mã:
    Function TextToUTF8(ByVal text As String) As String
    '    ket qua tra ve co dang %c1%c2...%cn. c1, c2, ..., cn la cac ma o dang hex cua chuoi text o dang UTF8.
    '    Noi cach khac là phai chuyen text sang dang utf8, rồi thay moi ky tu utf8 bang %<ma hex cua ky tu utf8>
      Dim data() As Byte
      Dim i As Integer
      Dim file As String
      file = Environ("temp") & "\translatetext.txt"
      With CreateObject("ADODB.Stream")
        .Charset = "utf-8"
        .Mode = 3
        .Type = 2
        .Open
        .WriteText text
        .Flush
        .Position = 0
        .Type = 1
        .SaveToFile file, 2
        .Close
        .Open
        .LoadFromFile file
        data = .Read()
        For i = 3 To UBound(data)
          TextToUTF8 = TextToUTF8 & "%" & Right("00" & Hex(data(i)), 2)
        Next
        .Close
      End With
    End Function
     

    File đính kèm

    Lần chỉnh sửa cuối:
    Upvote 0
    Đơn giản, hiệu quả: cám ơn bác batman1 đã có bài kịp thời giúp ích cho người hỏi và ai khác cần trong cuộc chiến đại dịch này.

    Việc ghi file âm thanh từ người sử dụng là đơn giản và thân thiện hơn sử dụng giọng google.
     
    Upvote 0
    Tôi thấy trong VBA có đối tượng Speech và thư viện Microsoft Speech Object Library, mặc định nó phát ra giong đọc tiếng Anh, bạn HeSanbi, anh batman1 có ngâm cứu qua cái này chưa? có cách gì câu móc, thay đổi thành ngôn ngữ tiếng Việt không nhỉ? Tôi đọc tài liệu mà cũng chưa hiểu gì về nó.

    Mã:
    Application.Speech.Speak ("1 2 3 4 5 6")

    Dùng thư viện MS Speech lib: dùng Userform.
    Mã:
    Sub Test2()
        DocChuoi2 Me.TextBox1, "ENGLISH"
    End Sub
    
    Private Sub DocChuoi2(sChuoi As String, Language As String)
        Dim Voc As SpeechLib.SpVoice
        Set Voc = New SpVoice
        With Voc
            If UCase(Language) = "ENGLISH" Then
                Set .Voice = .GetVoices.Item(0)
            ElseIf UCase(Language) = "VIETNAMESE" Then  '<-- làm sao thêm ngôn ngu TV
                Set .Voice = .GetVoices.Item(1)
            End If
            .Rate = -1
            .Volume = 100
            .Speak sChuoi
        End With
    End Sub
     
    Upvote 0
    Tôi thấy trong VBA có đối tượng Speech và thư viện Microsoft Speech Object Library, mặc định nó phát ra giong đọc tiếng Anh, bạn HeSanbi, anh batman1 có ngâm cứu qua cái này chưa? có cách gì câu móc, thay đổi thành ngôn ngữ tiếng Việt không nhỉ? Tôi đọc tài liệu mà cũng chưa hiểu gì về nó.

    Mã:
    Application.Speech.Speak ("1 2 3 4 5 6")

    Dùng thư viện MS Speech lib: dùng Userform.
    Mã:
    Sub Test2()
        DocChuoi2 Me.TextBox1, "ENGLISH"
    End Sub
    
    Private Sub DocChuoi2(sChuoi As String, Language As String)
        Dim Voc As SpeechLib.SpVoice
        Set Voc = New SpVoice
        With Voc
            If UCase(Language) = "ENGLISH" Then
                Set .Voice = .GetVoices.Item(0)
            ElseIf UCase(Language) = "VIETNAMESE" Then  '<-- làm sao thêm ngôn ngu TV
                Set .Voice = .GetVoices.Item(1)
            End If
            .Rate = -1
            .Volume = 100
            .Speak sChuoi
        End With
    End Sub
    Tôi chưa ngâm cứu. Đơn giản vì tôi chưa cài giọng Việt Nam nào cả. Tôi nghĩ là phải cài giọng Việt, vì nếu không thì lấy đâu ra anh / chị đọc tiếng Việt? Mà là cài giọng Việt trong system.

    Muốn vọc gì thì trước tiên phải có người đọc trong system.

    Nếu bạn đã có giọng Việt trong system rồi thì vd. bạn có 3 giọng: Anh, Anh, Việt. Bạn hãy test 3 lần cho:
    - .GetVoices.Item(0)
    - .GetVoices.Item(1)
    - .GetVoices.Item(2)

    Thế thôi.
     
    Upvote 0
    Tôi thấy trong VBA có đối tượng Speech và thư viện Microsoft Speech Object Library, mặc định nó phát ra giong đọc tiếng Anh, bạn HeSanbi, anh batman1 có ngâm cứu qua cái này chưa? có cách gì câu móc, thay đổi thành ngôn ngữ tiếng Việt không nhỉ? Tôi đọc tài liệu mà cũng chưa hiểu gì về nó.
    ----------------------------------------------------------

    Thư viện này không hỗ trợ đọc tiếng việt Microsoft An trong Window 10


    Để đọc tiếng việt cần sử dụng phần mền bên thứ 3 và sử dụng thư viện này để đúc kết


    Tôi đã viết như thế này:


    ----------------------------
    JavaScript:
    '                    _,
    ' ___   _   _  _ ___(_)
    '/ __| / \ | \| | _ | |
    '\__ \/ \ \| \\ | _ \ |
    '|___/_/ \_|_|\_|___/_|
    '
    ' Speaker
    Option Explicit
    #If VBA7 Then
      Private Declare PtrSafe Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
      Private Declare PtrSafe Function GetShortPathName Lib "KERNEL32" Alias "GetShortPathNameW" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
    #Else
      Private Declare  Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
      Private Declare  Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameW" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
    #End If
    
    '                    _,
    ' ___   _   _  _ ___(_)
    '/ __| / \ | \| | _ | |
    '\__ \/ \ \| \\ | _ \ |
    '|___/_/ \_|_|\_|___/_|
    '
    '==================================================================================================
    
    Private Sub SpeakerXL_Busy_Test()
      Call SpeakerXL_Busy("My NickName is Sanbi", 1.5)
    End Sub
    
    Sub SpeakerXL_Busy(Optional Text As String, _
                  Optional Speed As Double = 1, _
                  Optional Volume As Integer = 100, _
                  Optional Speaker As Integer = 0)
      DoEvents
      Dim oVoice As SpeechLib.SpVoice
      Set oVoice = VBA.CreateObject("SAPI.SpVoice")
      Set oVoice.Voice = oVoice.GetVoices.Item(Speaker)
      oVoice.Rate = Speed
      oVoice.Volume = Volume
      oVoice.Speak Text
      Set oVoice = Nothing
    End Sub
    '                    _,
    ' ___   _   _  _ ___(_)
    '/ __| / \ | \| | _ | |
    '\__ \/ \ \| \\ | _ \ |
    '|___/_/ \_|_|\_|___/_|
    '
    Private Sub SpeakerXL_test()
      Call SpeakerXL("My NickName is Sanbi", 1.5, 100, 0, 0)
    End Sub
    Sub SpeakerXL(Optional Text As String, _
                  Optional Speed As Double = 1, _
                  Optional Volume As Integer = 100, _
                  Optional Speaker As Integer = 0)
      On Error Resume Next
      Call mciSendString("close all", "", 0, 0)
      Const SAFT48kHz16BitStereo = 39
      Const SSFMCreateForWrite = 3
      Dim oFileStream As SpeechLib.SpFileStream
      Dim oVoice As SpeechLib.SpVoice
      Dim xpath As String
      xpath = VBA.Environ$("temp") & "\Sample.wav"
      GoSub Save
      xpath = GetShortPath(xpath)
      Set oFileStream = VBA.CreateObject("SAPI.SpFileStream")
      oFileStream.Format.Type = SAFT48kHz16BitStereo
      oFileStream.Open xpath, SSFMCreateForWrite, True
      Set oVoice = VBA.CreateObject("SAPI.SpVoice")
      Set oVoice.Voice = oVoice.GetVoices.Item(Speaker)
    
    
    '    Dim I As Long
    '    For I = 0 To oVoice.GetVoices.Count - 1
    '      Set oVoice.Voice = oVoice.GetVoices.Item(I)
    '      Debug.Print oVoice.Voice.GetDescription
    '    Next
    
    
      Set oVoice.AudioOutputStream = oFileStream
      oVoice.Volume = 100
      oVoice.Speak Text, SpeechLib.SpeechVoiceSpeakFlags.SVSFDefault
      oVoice.Rate = Speed
      oVoice.Volume = 100
      oFileStream.Close
      Set oFileStream = Nothing
      Set oVoice = Nothing
    
      Call mciSendString("open " & xpath & " alias fmusic", "", 0, 0)
      Call mciSendString("play fmusic", "", 0, 0)
    Exit Sub
    Save:
      With VBA.CreateObject("ADODB.Stream")
        .Type = 2 'Stream type
        .Charset = "utf-8" 'or utf-16 etc
        .Open
        .WriteText ""
        .SaveToFile xpath, 2 'Save binary data To disk
      End With
      VBA.err.Clear
    Return
    End Sub
    
    Private Function GetShortPath(ByVal Path As String) As String
      Dim ret&, Buff As String * 512
      ret = GetShortPathName(VBA.StrConv(Path, 64), Buff, 512)
      GetShortPath = VBA.Left(StrConv(Buff, 128), ret)
    End Function
     
    Lần chỉnh sửa cuối:
    Upvote 0
    Những ai chưa biết cách lấy tập tin mp3 của google về máy thì xem tôi "biểu diễn" trong tập tin. :D
    -----------------------------------


    Kĩ thuật code của bác batman1, nhìn phát chán, khiến tôi không muốn chạm vào VBE để viết một đoạn code nào nữa, một lập trình viên "lâu đời" như bác cứ viết code theo kiểu "amater", tôi tải về là không còn muốn test file.

    Lỡ "show" thì show cho "ngầu" và hoành tráng chứ bác.
    ------------------------------


    Ứng dụng Google Đọc tôi đang hoàn thiện:
    (Code bên dưới sử dụng một kỹ thuật chạy ứng dụng ngoài tiến trình, kỹ thuật này giúp không sử dụng Lớp Application chính phục vụ tính toán)

    FormatExcel.png
    ------------------------------
    JavaScript:
    '==============================================================
    ' GOOGLE SPEECH
    '==============================================================
    Option Explicit
    '//////////////////////////////////////////////////////////////
    Public Const INVALID_HANDLE_VALUE = -1
    Public Const ERROR_SHARING_VIOLATION = 32
    Public Const OPEN_ALWAYS = 4
    Public Const FILE_SHARE_READ = &H1
    Public Const GENERIC_READ = &H80000000
    Public Const GENERIC_WRITE = &H40000000
    Public Const GENERIC_EXECUTE = &H20000000
    Public Const GENERIC_ALL = &H10000000
    '//////////////////////////////////////////////////////////////
    #If VBA7 Then
      Public Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
      Public Declare PtrSafe Function ShowWindow Lib "user32" (ByVal hwnd As LongPtr, ByVal nCmdShow As Long) As Long
      Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long
      Private Declare PtrSafe Function GetLastError Lib "kernel32" () As Long
      Private Declare PtrSafe Function CreateFileW Lib "kernel32" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr
      Private Declare PtrSafe Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
      Private Declare PtrSafe Function mciGetErrorString Lib "winmm.dll" Alias "mciGetErrorStringA" (ByVal dwError As Long, ByVal lpstrBuffer As String, ByVal uLength As Long) As Long
      Private Declare PtrSafe Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameW" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
      Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
      Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
      Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
    #Else
      Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
      Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
      Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
      Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
      Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
      Private Declare Function GetLastError Lib "kernel32" () As Long
      Private Declare Function CreateFileW Lib "kernel32" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
      Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
      Private Declare Function mciGetErrorString Lib "winmm.dll" Alias "mciGetErrorStringA" (ByVal dwError As Long, ByVal lpstrBuffer As String, ByVal uLength As Long) As Long
      Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameW" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
      Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
    #End If
    '//////////////////////////////////////////////////////////////
    #If Win64 Then
      Private Pri_TimerID As LongPtr
    #Else
      Private Pri_TimerID As Long
    #End If
    '//////////////////////////////////////////////////////////////
    Private Type PlayerPlaying
      File As String
      Index As Integer
      list As Variant
      Volume As Long
      Speed As Double
    End Type
    '//////////////////////////////////////////////////////////////
    Public Const Reg_Section = "Settings"
    '//////////////////////////////////////////////////////////////
    Public Const ROOT_NAME = "GSpeechXL"
    Public Const ROOT_FILE = ROOT_NAME & ".xlam"
    Public Const ROOT_FILE_SV = ROOT_NAME & "_sv.xlam"
    '//////////////////////////////////////////////////////////////
    Public Const LimitLen = 180
    Public Const parameter = "/safe"
    '//////////////////////////////////////////////////////////////
    ' SHORTCUT KEY
    Public Const SK_SPEECH_ONLY = "^+c"
    Public Const SK_SPEECH_TRANSLATE = "^+a"
    Public Const SK_SETTINGS = "^+%s"
    '//////////////////////////////////////////////////////////////
    Public cApp As CAppEvents
    Public APP_MAIN As Object
    Public APP_ As Object
    Private PNP As PlayerPlaying
    Private DoTime As Date
    Private Pri_Text As String
    Private Pri_LangSpeakDefault As String
    Private Pri_LangTranslate As String
    Private Pri_Translate As Boolean
    '///////////////////|
    ' __   _____   _ ®  |
    ' \ \ / / _ | / \   |
    '  \ \ /| _ \/ / \  |
    '   \_/ |___/_/ \_\ |
    '                   |
    '///////////////////|
    '==============================================================
    '//////////////////////////////////////////////////////////////
    Private Sub GSpeech_OnTime_test()
      Dim S$
    'Chinese:  S = ThisWorkbook.VBProject.VBComponents("form_GSpeechXL").Designer.Controls("Label1").Caption
    'Japanese:  S = ThisWorkbook.VBProject.VBComponents("form_GSpeechXL").Designer.Controls("Label2").Caption
    'Korea:  S = ThisWorkbook.VBProject.VBComponents("form_GSpeechXL").Designer.Controls("Label3").Caption
    'Arabi:  S = ThisWorkbook.VBProject.VBComponents("form_GSpeechXL").Designer.Controls("Label4").Caption
    'Vietnamese:  S = ThisWorkbook.VBProject.VBComponents("form_GSpeechXL").Designer.Controls("Label5").Caption
      SpeechXL S, "vi", 1, 100
    End Sub
    '//////////////////////////////////////////////////////////////
    
    '///////////////////|
    ' __   _____   _ ®  |
    ' \ \ / / _ | / \   |
    '  \ \ /| _ \/ / \  |
    '   \_/ |___/_/ \_\ |
    '                   |
    '///////////////////|
    ' Main Function
    '==============================================================
    Function SpeechXL(ByVal Text As String, _
             Optional ByVal LangSpeakDefault As String = "", _
             Optional ByVal Speed As Double = 1.2, _
             Optional ByVal Volume As Byte = 90, _
             Optional ByVal oAPP As Object) As String
      On Error Resume Next
      SpeechXL = "Speech"
      PNP.Speed = VBA.IIf(Speed < 0.5, 0.5, VBA.IIf(Speed > 4, 4, Speed))
      PNP.Volume = VBA.IIf(Volume < 20, 20, VBA.IIf(Volume > 100, 100, Volume))
      Pri_Text = Text
      Pri_LangSpeakDefault = LangSpeakDefault
      Set APP_ = oAPP
      If Pri_TimerID <> 0 Then KillTimer 0&, Pri_TimerID
      Pri_TimerID = SetTimer(0&, 0&, 0, AddressOf SpeechXL_Run)
    End Function
    '//////////////////////////////////////////////////////////////
    Public Sub GSPEECH_STOP()
       On Error GoTo Main
       oSpeechXL.Parent.OnTime VBA.Now, "'" & ROOT_FILE_SV & "'!GSPEECH_End"
    Exit Sub
    Main:
      Application.OnTime VBA.Now, "'" & ThisWorkbook.Name & "'!GSPEECH_End"
    End Sub
    '///////////////////|
    ' __   _____   _ ®  |
    ' \ \ / / _ | / \   |
    '  \ \ /| _ \/ / \  |
    '   \_/ |___/_/ \_\ |
    '                   |
    '///////////////////|
    ' START APP WITH NEW PROCESS
    '==============================================================
    Private Sub GSPEECH_OPEN_SV_RUN()
      Call GSPEECH_OPEN_SV(True)
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub ShowWindowUI()
      #If Win64 Then
        Dim hwnd As LongPtr
      #Else
        Dim hwnd As Long
      #End If
      Static I As Long
      I = VBA.IIf(I = 0, 9, 0)
      Dim WB As Object
      Set WB = oSpeechXL
      If WB Is Nothing Then Exit Sub
      hwnd = WB.Parent.hwnd
      ShowWindow hwnd, I
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub CloseAppX()
      Call IsOpenX(True)
    End Sub
    '///////////////////|
    ' __   _____   _ ®  |
    ' \ \ / / _ | / \   |
    '  \ \ /| _ \/ / \  |
    '   \_/ |___/_/ \_\ |
    '                   |
    '///////////////////|
    ' PATH
    '==============================================================
    Private Function PATH_SYS_TEMP() As String
      PATH_SYS_TEMP = VBA.IIf(VBA.Environ("tmp") <> "", VBA.Environ("tmp"), VBA.Environ("temp"))
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function PATH_GSPEECH_STARTUP() As String
      PATH_GSPEECH_STARTUP = Application.StartupPath & "\" & ROOT_FILE_SV
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function ROOT_NAME_() As String
      ROOT_NAME_ = ROOT_NAME & CStr(PNP.Index Mod 2)
    End Function
    '//////////////////////////////////////////////////////////////
    Private Sub GSPEECH_Kill()
      On Error Resume Next
      Call GSPEECH_PlayerStop
      Call VBA.Kill(PATH_SYS_TEMP & "\" & ROOT_NAME & "\translate_tts1.mp3")
      Call VBA.Kill(PATH_SYS_TEMP & "\" & ROOT_NAME & "\*.*")
    End Sub
    '///////////////////|
    ' __   _____   _ ®  |
    ' \ \ / / _ | / \   |
    '  \ \ /| _ \/ / \  |
    '   \_/ |___/_/ \_\ |
    '                   |
    '///////////////////|
    '==============================================================
    ' GOOGLE Speech Start
    '==============================================================
    
    '//////////////////////////////////////////////////////////////
    Private Sub GSPEECH_Status(Optional Clean As Boolean)
      If APP_ Is Nothing Then
        Application.StatusBar = VBA.IIf(Clean, "", PNP.list(2, PNP.Index))
      Else
        APP_.StatusBar = VBA.IIf(Clean, "", PNP.list(2, PNP.Index))
      End If
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub GSPEECH_PlayerStop()
       On Error Resume Next
       Call mciSendString("Close " & ROOT_NAME & "1", "", 0, 0)
       Call mciSendString("Close " & ROOT_NAME & "0", "", 0, 0)
       Call GSPEECH_Status(True)
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub GSPEECH_End()
      On Error Resume Next
      Call GSPEECH_PlayerStop
      Application.OnTime VBA.Now, "'" & ThisWorkbook.Name & "'!GSPEECH_PlayerStop", , False
      Application.OnTime DoTime, "'" & ThisWorkbook.Name & "'!GSpeech_CheckPlayNext", , False
      'Application.OnTime VBA.Now, "'" & ThisWorkbook.Name & "'!GSPEECH_Kill"
      Call GSPEECH_Status(True)
      Set APP_ = Nothing
      On Error GoTo 0
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub GSPEECH_OPEN_SV(Optional Reset As Boolean, Optional Timeout As Integer = 0)
      Call copyProject(Reset)
      'VBA.Shell "cmd.exe /S /C timeout /t " & Timeout & " /nobreak " & _
                 "&& START """ & ROOT_NAME & """ """ & Application.Path & "\EXCEL.EXE"" /x " & parameter & " """ & PATH_GSPEECH_STARTUP & """", 0
      VBA.Shell "cmd.exe /S /C START """ & ROOT_NAME & """ """ & Application.Path & "\EXCEL.EXE"" /x " & parameter & " """ & PATH_GSPEECH_STARTUP & """", 0
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub SpeechXL_Run()
      If Pri_TimerID <> 0 Then KillTimer 0&, Pri_TimerID
      On Error GoTo Main
      oSpeechXL.Parent.Run "'" & ROOT_FILE_SV & "'!GSpeech_OnTime", Pri_Text, Pri_LangSpeakDefault, PNP.Speed, PNP.Volume
    Exit Sub
    Main:
      Application.Run "'" & ThisWorkbook.Name & "'!GSpeech_OnTime", Pri_Text, Pri_LangSpeakDefault, PNP.Speed, PNP.Volume
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub GSpeech_OnTime(ByVal Text As String, _
              Optional ByVal LangSpeakDefault$ = "", _
              Optional ByVal Speed As Double = 1.3, _
              Optional ByVal Volume As Byte = 90, _
              Optional ByVal oAPP As Object)
      PNP.Index = 0
      PNP.Speed = VBA.IIf(Speed < 0.5, 0.5, VBA.IIf(Speed > 4, 4, Speed))
      PNP.Volume = VBA.IIf(Volume < 20, 20, VBA.IIf(Volume > 100, 100, Volume))
      Pri_Text = Text: Pri_LangSpeakDefault = LangSpeakDefault
      Set APP_ = oAPP
      Application.OnTime VBA.Now, "'" & ThisWorkbook.Name & "'!GSpeech_Run"
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub GSpeech_Run()
      On Error Resume Next
      If Pri_Text = "" Then Exit Sub
      '--------------------------------------
      Dim iRun As Boolean, Hieroglyphs As Boolean
      Dim L%, I%, K%, Ti As Double, total()
      Dim Text As String, T As String, LT As String, rT As String, Tmp As String, URL$
      Dim gspeech_temp As String
      gspeech_temp = PATH_SYS_TEMP & "\" & ROOT_NAME & "\"
      Call GSPEECH_PlayerStop
      Call CreateFolder(gspeech_temp)
      Const Link = "translate.google.com/translate_tts?ie=utf-8&client=tw-ob&tl="
     
      If Pri_LangSpeakDefault = "" Then GoSub Detect
      Select Case VBA.LCase(Pri_LangSpeakDefault)
      Case "ja", "zh-cn", "zh-tw", "ar", "ko": Hieroglyphs = True
      End Select
      URL = "http://" & Link & Pri_LangSpeakDefault & "&q="
      '--------------------------------------
      GoSub Disjoint
      If K > 0 And Not iRun Then
        Call GSpeech_ListPlayNext
      End If
    Exit Sub
    
    Disjoint:
      K = 0
      Text = Pri_Text
      Do
        L = Len(Text): If L <= 0 Then Exit Do
        K = K + 1
        ReDim Preserve total(1 To 2, 1 To K)
        total(1, K) = gspeech_temp & "translate_tts" & K & ".mp3"
        If L <= LimitLen Then total(2, K) = Text: GoSub MakeArr: Exit Do
        total(2, K) = VBA.Left(Text, LimitLen)
        rT = VBA.Right(Text, L - LimitLen)
        If Not Hieroglyphs Then
          I = VBA.InStrRev(1, total(2, K), " ")
          If I + 20 > LimitLen Then
            total(2, K) = VBA.Left(total(2, K), I - 1)
            rT = VBA.Right(Text, L - I - 2)
            If VBA.Left(rT, 1) Like "[,;:._ ]" Then rT = VBA.Right(rT, Len(rT) - 1)
          End If
        End If
        Text = rT
        GoSub MakeArr
        DoEvents
      Loop
    Return
    MakeArr:
      DoEvents
     
      Tmp = VBA.Replace(VBA.Replace(VBA.Replace(VBA.Replace(total(2, K), ")", "."), "(", "."), "]", "."), "[", ".")
    
      If URLDownloadToFile(0, URL & EncodeURL(Tmp), total(1, K), 0, 0) <> 0 Then
        GoTo EndAndKill
      End If
      total(1, K) = ShortPath(total(1, K))
      PNP.list = total
      If Not iRun Then
        iRun = Dir(gspeech_temp & "translate_tts1.mp3", vbSystem) <> ""
        If iRun Then Call GSpeech_ListPlayNext
      End If
    Return
    Detect:
      DoEvents
      If Pri_Text = "" Then Return
      Dim strInput$
      With oGlb_WinHttp_DL 'VBA.CreateObject("WinHttp.WinHttpRequest.5.1")
        .Open "GET", "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto" & _
              VBA.IIf("" <> "&tl=", "", "&tl=vi") & "&dt=t&q=" & _
              EncodeURL(Left(Replace(Pri_Text, Chr(10), " "), 50)), False
        .setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
        .setRequestHeader "Content-Type", "applicaton/X-www-form-urlencoded"
        .Send "": If .Status <> 200 Then GoTo EndAndKill
        strInput = VBA.Replace(.responseText, VBA.Chr(10), "")
        Pri_LangSpeakDefault = VBA.Replace(VBA.Replace(VBA.Split(VBA.Right(strInput, Len(strInput) - VBA.InStr(strInput, "],[""") - 2), "],")(0), """", ""), "]", "")
        strInput = ""
      End With
    Return
    EndAndKill:
    Application.OnTime VBA.Now, "'" & ThisWorkbook.Name & "'!GSpeech_End"
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub GSpeech_ListPlayNext()
      On Error Resume Next
      Application.OnTime DoTime, "'" & ThisWorkbook.Name & "'!GSpeech_CheckPlayNext", , False
      '-----------------------------
      Dim idx As Long, ListCount As Long
      ListCount = UBound(PNP.list, 2)
      idx = PNP.Index + 1
      If idx <= ListCount Then
        PNP.Index = idx
        PNP.File = PNP.list(1, idx)
        Call GSpeech_FileOpen
        DoTime = (GSpeech_GetLength - 2500)
        DoTime = VBA.IIf(DoTime < 1000, 0, DoTime / 1000 / PNP.Speed)
        DoTime = VBA.Now + VBA.TimeSerial(0, 0, DoTime)
        Application.OnTime DoTime, "'" & ThisWorkbook.Name & "'!GSpeech_CheckPlayNext"
        Call GSPEECH_Status
      Else
        Application.OnTime VBA.Now + VBA.TimeSerial(0, 0, 1), "'" & ThisWorkbook.Name & "'!GSPEECH_PlayerStop"
      End If
      On Error GoTo 0
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub GSpeech_CheckPlayNext()
      Dim T1 As Long, T2 As Long
      T1 = GSpeech_GetCurPos: T2 = GSpeech_GetLength
      If T1 = 0 Or T2 = 0 Then Exit Sub
      If T1 >= T2 - 1000 Then
        Application.OnTime VBA.Now, "'" & ThisWorkbook.Name & "'!GSpeech_ListPlayNext"
      Else
        Application.OnTime VBA.Now + VBA.TimeSerial(0, 0, 1) * 0.7, "'" & ThisWorkbook.Name & "'!GSpeech_CheckPlayNext"
      End If
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub GSpeech_FileOpen()
      Dim lRet&, sError As String * 255
      Call mciSendString("Close " & ROOT_NAME_, "", 0, 0)
      lRet = mciSendString("open """ & PNP.File & """ alias " & ROOT_NAME_, "", 0, 0)
      If lRet <> 0 Then mciGetErrorString lRet, sError, 255: Exit Sub
      Call mciSendString("set " & ROOT_NAME_ & " Speed " & CStr(Int(PNP.Speed * 1000)), "", 0, 0)
      Call mciSendString("setaudio " & ROOT_NAME_ & " Volume to " & PNP.Volume * 10, "", 0, 0)
      Call mciSendString("Play " & ROOT_NAME_, "", 0, 0)
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Function GSpeech_info() As String
      Dim lRet&, S As String * 255: S = VBA.Space(255): lRet = 255
      On Error Resume Next
      Call mciSendString("info " & ROOT_NAME_ & " file", S, lRet, 0)
      GSpeech_info = VBA.Left(S, VBA.InStr(S, VBA.vbNullChar) - 1)
      On Error GoTo 0
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function GSpeech_GetLength() As Long
      Dim lRet&, S As String * 255: S = VBA.Space(255)
      On Error Resume Next
      lRet = mciSendString("status " & ROOT_NAME_ & " length", S, 255, 0)
      If lRet = 0 Then GSpeech_GetLength& = CLng(S)
      On Error GoTo 0
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function GSpeech_GetCurPos() As Long
      Dim lRet&, S As String * 255: S = VBA.Space(255)
      On Error Resume Next
      lRet = mciSendString("status " & ROOT_NAME_ & " position wait", S, 255, 0)
      If lRet = 0 Then GSpeech_GetCurPos = CLng(S)
      On Error GoTo 0
    End Function
    '///////////////////|
    ' __   _____   _ ®  |
    ' \ \ / / _ | / \   |
    '  \ \ /| _ \/ / \  |
    '   \_/ |___/_/ \_\ |
    '                   |
    '///////////////////|
    Private Function EncodeURL(strText)
        Static objHtmlfile As Object
        If objHtmlfile Is Nothing Then
            Set objHtmlfile = VBA.CreateObject("htmlfile")
            objHtmlfile.parentWindow.execScript "function encode(s) {return encodeURIComponent(s)}", "jscript"
        End If
        EncodeURL = objHtmlfile.parentWindow.encode(strText)
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function ShortPath(ByVal LongPath As String) As String
      Dim ret&, Buff As String * 512
      ret = GetShortPathName(StrConv(LongPath, 64), Buff, 512)
      ShortPath = Left(StrConv(Buff, 128), ret)
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function CreateFolder(ByVal FolderPath As String, Optional ByRef FileSystem As Object) As Boolean
      Dim FolderArray, Tmp$, I As Integer, UB As Integer, tFolder$
      tFolder = FolderPath
      If VBA.Right(tFolder, 1) = "\" Then tFolder = VBA.Left(tFolder, VBA.Len(tFolder) - 1)
      If tFolder Like "\\*\*" Then tFolder = VBA.Strings.Replace(tFolder, "\", "@", 1, 3)
      FolderArray = VBA.Split(tFolder, "\")
      FolderArray(0) = VBA.Strings.Replace(FolderArray(0), "@", "\", 1, 3)
      On Error GoTo Ends
      If FileSystem Is Nothing Then
        Set FileSystem = oGlb_FSO 'VBA.CreateObject("Scripting.FileSystemObject")
      End If
      UB = UBound(FolderArray)
      With FileSystem
        For I = 0 To UB
          Tmp = Tmp & FolderArray(I) & "\"
          If Not .FolderExists(Tmp) Then .CreateFolder (Tmp)
          CreateFolder = (I = UB) And Len(FolderArray(I)) > 0 And FolderArray(I) <> " "
        Next
      End With
    Ends:
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function oSpeechXL() As Object
      Static o As Object, X As Boolean
      If o Is Nothing And Not X Then
        X = IsOpenX: If X Then Set o = VBA.GetObject(PATH_GSPEECH_STARTUP)
      End If
      Set oSpeechXL = o
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function oGlb_FSO() As Object
      Static o As Object
      If o Is Nothing Then Set o = VBA.CreateObject("Scripting.FileSystemObject")
      Set oGlb_FSO = o
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function oGlb_WinHttp_DL() As Object
      Static o As Object
      If o Is Nothing Then Set o = VBA.CreateObject("WinHttp.WinHttpRequest.5.1")
      Set oGlb_WinHttp_DL = o
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function IsOpenA(ByVal FileName As String) As Boolean
      Const INVALID_HANDLE_VALUE = -1
      Const ERROR_SHARING_VIOLATION = 32
      #If Win64 Then
        Dim hFile As LongPtr
      #Else
        Dim hFile As Long
      #End If
      hFile = CreateFileW(VBA.StrConv(FileName, vbUnicode), GENERIC_READ, FILE_SHARE_READ, 0&, OPEN_ALWAYS, 0, 0)
      If hFile = INVALID_HANDLE_VALUE Then
        If GetLastError() = ERROR_SHARING_VIOLATION Then
        Else
        End If
        IsOpenA = True
      Else
        CloseHandle hFile
      End If
    End Function
    '//////////////////////////////////////////////////////////////
    Private Function IsOpenX(Optional terminate As Boolean, Optional bKill As Boolean) As Boolean
      On Error Resume Next
      Dim F As String, o
      F = PATH_GSPEECH_STARTUP
      If Not IsOpenA(F) Then Exit Function
      For Each o In VBA.GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * from Win32_Process Where Name ='excel.exe'")
        If VBA.LCase(o.commandLine) Like VBA.LCase("*/x *" & parameter & " *" & F & "*") Then
          If terminate Then
            If bKill Then Kill F
            o.terminate
          End If
          IsOpenX = True: Exit For
        End If
      Next
      On Error GoTo 0
    End Function
    '//////////////////////////////////////////////////////////////
    Private Sub ClientApp_Close()
      On Error Resume Next
      Workbooks(ROOT_FILE_SV).Close False
      On Error GoTo 0
    End Sub
    '//////////////////////////////////////////////////////////////
    Private Sub copyProject(Optional Reset As Boolean)
      On Error Resume Next
      Dim P As String, K As Integer, WB As Object
      P = PATH_GSPEECH_STARTUP
      If StrComp(ThisWorkbook.Name, ROOT_FILE, 1) <> 0 Then Exit Sub
      If VBA.Dir(P, vbSystem) <> "" Then
        If Reset Then
          Set WB = Workbooks(ROOT_FILE_SV)
          If StrComp(WB.FullName, P, 1) = 0 Then
            WB.Close False
          End If
          Call IsOpenX(True)
          Kill P
          Do Until VBA.Dir(P, vbSystem) = ""
            Application.Wait VBA.Now + VBA.TimeSerial(0, 0, 1)
            K = K + 1: If K > 5 Then Exit Do
          Loop
          ThisWorkbook.SaveCopyAs P
        End If
      Else
        ThisWorkbook.SaveCopyAs P
      End If
      K = 0
      Do Until VBA.Dir(P, vbSystem) <> ""
        Application.Wait VBA.Now + VBA.TimeSerial(0, 0, 1)
        K = K + 1: If K > 5 Then Exit Do
      Loop
      On Error GoTo 0
    End Sub
    '//////////////////////////////////////////////////////////////
    
    Private Sub GSpeech_Selection()
     
    End Sub
    Private Sub GSpeech_Settings()
      On Error Resume Next
      Dim V As Boolean
      V = form_GSpeechXL.Visible
      If Not V Then form_GSpeechXL.Show 0 Else VBA.Unload form_GSpeechXL
      On Error GoTo 0
    End Sub
    
    '//////////////////////////////////////////////////////////////
    Sub DesignerChangeThemeOfFormxxx()
      Dim oCur As Object, VBComp
     
      On Error Resume Next
    
      Set VBComp = ThisWorkbook.VBProject.VBComponents("form_GSpeechXL")
      Set oCur = VBComp.Designer.Controls("btn_Exit").MouseIcon
     
      Dim Ctr
      For Each Ctr In VBComp.Designer.Controls
        Select Case VBA.Left(VBA.LCase(Ctr.Name), 3)
        Case "spe", "vol"
          Ctr.MousePointer = 99
          Set Ctr.MouseIcon = oCur
        End Select
      Next
    
    End Sub
    
    '//////////////////////////////////////////////////////////////
    Private Function googleLanguageSupport( _
              Optional SingleList As Integer = 0, _
              Optional Auto As Boolean) As Variant
    ' Last Edit: 31/03/2020 21:54
      Dim Arr()
      If Auto Then
        ReDim Arr(1 To 2, 104)
        Arr(1, 0) = "Auto":                    Arr(2, 0) = "Auto"
      Else
        ReDim Arr(1 To 2, 1 To 104)
      End If
      Arr(1, 1) = "English":                          Arr(2, 1) = "en"
      Arr(1, 2) = "Afrikaans":                        Arr(2, 2) = "af"
      Arr(1, 3) = "Albanian":                         Arr(2, 3) = "sq"
      Arr(1, 4) = "Amharic":                          Arr(2, 4) = "am"
      Arr(1, 5) = "Arabic":                           Arr(2, 5) = "ar"
      Arr(1, 6) = "Armenian":                         Arr(2, 6) = "hy"
      Arr(1, 7) = "Azerbaijani":                      Arr(2, 7) = "az"
      Arr(1, 8) = "Basque":                           Arr(2, 8) = "eu"
      Arr(1, 9) = "Belarusian":                       Arr(2, 9) = "be"
      Arr(1, 10) = "Bengali":                         Arr(2, 10) = "bn"
      Arr(1, 11) = "Bosnian":                         Arr(2, 11) = "bs"
      Arr(1, 12) = "Bulgarian":                       Arr(2, 12) = "bg"
      Arr(1, 13) = "Catalan":                         Arr(2, 13) = "ca"
      Arr(1, 14) = "Cebuano":                         Arr(2, 14) = "ceb"
      Arr(1, 15) = "Chinese (Simplified)":            Arr(2, 15) = "zh-CN"
      Arr(1, 16) = "Chinese (Traditional)":           Arr(2, 16) = "zh-TW"
      Arr(1, 17) = "Corsican":                        Arr(2, 17) = "co"
      Arr(1, 18) = "Croatian":                        Arr(2, 18) = "hr"
      Arr(1, 19) = "Czech":                           Arr(2, 19) = "cs"
      Arr(1, 20) = "Danish":                          Arr(2, 20) = "da"
      Arr(1, 21) = "Dutch":                           Arr(2, 21) = "nl"
      Arr(1, 22) = "Esperanto":                       Arr(2, 22) = "eo"
      Arr(1, 23) = "Estonian":                        Arr(2, 23) = "et"
      Arr(1, 24) = "Finnish":                         Arr(2, 24) = "fi"
      Arr(1, 25) = "French":                          Arr(2, 25) = "fr"
      Arr(1, 26) = "Frisian":                         Arr(2, 26) = "fy"
      Arr(1, 27) = "Galician":                        Arr(2, 27) = "gl"
      Arr(1, 28) = "Georgian":                        Arr(2, 28) = "ka"
      Arr(1, 29) = "German":                          Arr(2, 29) = "de"
      Arr(1, 30) = "Greek":                           Arr(2, 30) = "el"
      Arr(1, 31) = "Gujarati":                        Arr(2, 31) = "gu"
      Arr(1, 32) = "Haitian Creole":                  Arr(2, 32) = "ht"
      Arr(1, 33) = "Hausa":                           Arr(2, 33) = "ha"
      Arr(1, 34) = "Hawaiian":                        Arr(2, 34) = "haw"
      Arr(1, 35) = "Hebrew":                          Arr(2, 35) = "he or iw"
      Arr(1, 36) = "Hindi":                           Arr(2, 36) = "hi"
      Arr(1, 37) = "Hmong":                           Arr(2, 37) = "hmn"
      Arr(1, 38) = "Hungarian":                       Arr(2, 38) = "hu"
      Arr(1, 39) = "Icelandic":                       Arr(2, 39) = "is"
      Arr(1, 40) = "Igbo":                            Arr(2, 40) = "ig"
      Arr(1, 41) = "Indonesian":                      Arr(2, 41) = "id"
      Arr(1, 42) = "Irish":                           Arr(2, 42) = "ga"
      Arr(1, 43) = "Italian":                         Arr(2, 43) = "it"
      Arr(1, 44) = "Japanese":                        Arr(2, 44) = "ja"
      Arr(1, 45) = "Javanese":                        Arr(2, 45) = "jv"
      Arr(1, 46) = "Kannada":                         Arr(2, 46) = "kn"
      Arr(1, 47) = "Kazakh":                          Arr(2, 47) = "kk"
      Arr(1, 48) = "Khmer":                           Arr(2, 48) = "km"
      Arr(1, 49) = "Korean":                          Arr(2, 49) = "ko"
      Arr(1, 50) = "Kurdish":                         Arr(2, 50) = "ku"
      Arr(1, 51) = "Kyrgyz":                          Arr(2, 51) = "ky"
      Arr(1, 52) = "Lao":                             Arr(2, 52) = "lo"
      Arr(1, 53) = "Latin":                           Arr(2, 53) = "la"
      Arr(1, 54) = "Latvian":                         Arr(2, 54) = "lv"
      Arr(1, 55) = "Lithuanian":                      Arr(2, 55) = "lt"
      Arr(1, 56) = "Luxembourgish":                   Arr(2, 56) = "lb"
      Arr(1, 57) = "Macedonian":                      Arr(2, 57) = "mk"
      Arr(1, 58) = "Malagasy":                        Arr(2, 58) = "mg"
      Arr(1, 59) = "Malay":                           Arr(2, 59) = "ms"
      Arr(1, 60) = "Malayalam":                       Arr(2, 60) = "ml"
      Arr(1, 61) = "Maltese":                         Arr(2, 61) = "mt"
      Arr(1, 62) = "Maori":                           Arr(2, 62) = "mi"
      Arr(1, 63) = "Marathi":                         Arr(2, 63) = "mr"
      Arr(1, 64) = "Mongolian":                       Arr(2, 64) = "mn"
      Arr(1, 65) = "Myanmar (Burmese)":               Arr(2, 65) = "my"
      Arr(1, 66) = "Nepali":                          Arr(2, 66) = "ne"
      Arr(1, 67) = "Norwegian":                       Arr(2, 67) = "no"
      Arr(1, 68) = "Nyanja (Chichewa)":               Arr(2, 68) = "ny"
      Arr(1, 69) = "Pashto":                          Arr(2, 69) = "ps"
      Arr(1, 70) = "Persian":                         Arr(2, 70) = "fa"
      Arr(1, 71) = "Polish":                          Arr(2, 71) = "pl"
      Arr(1, 72) = "Portuguese (Portugal, Brazil)":   Arr(2, 72) = "pt"
      Arr(1, 73) = "Punjabi":                         Arr(2, 73) = "pa"
      Arr(1, 74) = "Romanian":                        Arr(2, 74) = "ro"
      Arr(1, 75) = "Russian":                         Arr(2, 75) = "ru"
      Arr(1, 76) = "Samoan":                          Arr(2, 76) = "sm"
      Arr(1, 77) = "Scots Gaelic":                    Arr(2, 77) = "gd"
      Arr(1, 78) = "Serbian":                         Arr(2, 78) = "sr"
      Arr(1, 79) = "Sesotho":                         Arr(2, 79) = "st"
      Arr(1, 80) = "Shona":                           Arr(2, 80) = "sn"
      Arr(1, 81) = "Sindhi":                          Arr(2, 81) = "sd"
      Arr(1, 82) = "Sinhala (Sinhalese)":             Arr(2, 82) = "si"
      Arr(1, 83) = "Slovak":                          Arr(2, 83) = "sk"
      Arr(1, 84) = "Slovenian":                       Arr(2, 84) = "sl"
      Arr(1, 85) = "Somali":                          Arr(2, 85) = "so"
      Arr(1, 86) = "Spanish":                         Arr(2, 86) = "es"
      Arr(1, 87) = "Sundanese":                       Arr(2, 87) = "su"
      Arr(1, 88) = "Swahili":                         Arr(2, 88) = "sw"
      Arr(1, 89) = "Swedish":                         Arr(2, 89) = "sv"
      Arr(1, 90) = "Tagalog (Filipino)":              Arr(2, 90) = "tl"
      Arr(1, 91) = "Tajik":                           Arr(2, 91) = "tg"
      Arr(1, 92) = "Tamil":                           Arr(2, 92) = "ta"
      Arr(1, 93) = "Telugu":                          Arr(2, 93) = "te"
      Arr(1, 94) = "Thai":                            Arr(2, 94) = "th"
      Arr(1, 95) = "Turkish":                         Arr(2, 95) = "tr"
      Arr(1, 96) = "Ukrainian":                       Arr(2, 96) = "uk"
      Arr(1, 97) = "Urdu":                            Arr(2, 97) = "ur"
      Arr(1, 98) = "Uzbek":                           Arr(2, 98) = "uz"
      Arr(1, 99) = "Vietnamese":                      Arr(2, 99) = "vi"
      Arr(1, 100) = "Welsh":                          Arr(2, 100) = "cy"
      Arr(1, 101) = "Xhosa":                          Arr(2, 101) = "xh"
      Arr(1, 102) = "Yiddish":                        Arr(2, 102) = "yi"
      Arr(1, 103) = "Yoruba":                         Arr(2, 103) = "yo"
      Arr(1, 104) = "Zulu":                           Arr(2, 104) = "zu"
      Select Case SingleList
      Case 1: googleLanguageSupport = Application.Index(Arr, 1, 0)
      Case 2: googleLanguageSupport = Application.Index(Arr, 2, 0)
      Case Else: googleLanguageSupport = Arr
      End Select
    End Function
     
    Upvote 0
    Tôi cũng tự viết hàm utf8_encode.
    Hàm này chưa chuẩn anh ơi, anh xem trong file đính kèm nhé.

    Chỗ tải file thì link kia trả về là tập tin audio luôn nên theo em dùng URLDownloadToFile API cho nhanh.

    Vậy quy trình với TTS của Google đại khái: encode chuỗi và ghép vào link TTS, tải file audio, mở file audio.
     

    File đính kèm

    Upvote 0
    -------------------------------------


    Bạn tải file sau về sử dụng cho đơn giản.


    -------------------------------------
    Quá hay anh ơi. Code anh tuyệt vời trong lúc đọc âm thanh con chuột vẫn làm việc khác được. Vậy cho em có cách nào nó đọc cho nhiều ô không. Ví dụ em có B5:B500 bệnh nhân. em chỉ cần copy vô như thế này . thì em bấm 1 cái là nó đọc từ trên xuống dưới cho tiền khỏi phải thay đổi số cho những lần sau. Em cảm ơn ạ
    1585882037535.png
     
    Upvote 0
    Web KT

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

    Back
    Top Bottom