Giúp File Đọc Số ra Âm thanh dùng trong Khu Cách Ly COVID-19

Liên hệ QC

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

  • GoiSo.xlsb
    620.8 KB · Đọc: 80
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

  • google text to speech.xlsb
    24.2 KB · Đọc: 72
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

  • translate_tts.zip
    23 KB · Đọc: 50
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
Back
Top Bottom