使用Excel VBA或Javascript替换编程代码中的时间值

使用Excel VBA或Javascript替换编程代码中的时间值,javascript,vba,excel,Javascript,Vba,Excel,我正在尝试制作一首歌的滚动卡拉OK歌词。lyric软件输出一个代码,其中包含我需要转换的时间(以秒为单位) 同一首歌我有两个版本。一个运行速度较慢,为52 bpm(每分钟拍数),另一个运行速度较快,为104 bpm 我已经完成了第一个版本,花了很多时间。我想转换代码的方式,我可以得到更快的版本自动 下面是示例代码 <item dStartTime="4" dEndTime="8" n3DRhythm="2" str3DSceneLayoutFile=""> <t

我正在尝试制作一首歌的滚动卡拉OK歌词。lyric软件输出一个代码,其中包含我需要转换的时间(以秒为单位)

同一首歌我有两个版本。一个运行速度较慢,为52 bpm(每分钟拍数),另一个运行速度较快,为104 bpm

我已经完成了第一个版本,花了很多时间。我想转换代码的方式,我可以得到更快的版本自动

下面是示例代码

<item dStartTime="4" dEndTime="8" n3DRhythm="2" str3DSceneLayoutFile="">    
    <text>Batti Gul Meter Chalu</text>
</item> 
<item dStartTime="9.52" dEndTime="14.47" n3DRhythm="2" str3DSceneLayoutFile=""> 
    <text>rajj&lt;10.44&gt; ke&lt;10.99&gt; rulaya</text>
</item> 
<item dStartTime="14.47" dEndTime="19.06" n3DRhythm="2" str3DSceneLayoutFile="">    
    <text>rajj ke&lt;15.94&gt; hansaya</text>
</item> 

Batti Gul-Meter Chalu
rajj10.44 ke10.99 rulaya
rajj ke15.94 hansaya
我想转换如下所示的相同代码,其中以秒为单位的时间应该正好是带两个小数点的一半

<item dStartTime="2" dEndTime="4" n3DRhythm="2" str3DSceneLayoutFile="">    
    <text>Batti Gul Meter Chalu</text>
</item> 
<item dStartTime="4.76" dEndTime="7.24" n3DRhythm="2" str3DSceneLayoutFile="">  
    <text>rajj&lt;5.22&gt; ke&lt;5.50&gt; rulaya</text>
</item> 
<item dStartTime="7.24" dEndTime="9.53" n3DRhythm="2" str3DSceneLayoutFile="">  
    <text>rajj ke&lt;7.97&gt; hansaya</text>
</item> 

Batti Gul-Meter Chalu
rajj5.22 ke5.50 rulaya
rajj ke7.97 hansaya
我使用MS Excel中的代码,并尝试使用替换、连接和其他几个公式来实现我需要的功能,但我无法做到这一点,尽管Excel vba可以提供帮助,但我无法在vba中实现。请你们在这方面帮助我,因为我需要转换很多歌曲。你的善意帮助将节省很多时间。excel vba、javascript或任何其他替代代码的方法中的任何帮助

部分,我需要转换
dstartime
dEndTime

部分,我需要转换任何看起来像数字的东西


谢谢

在Javascript中,您可以使用
DOMParser
将字符串转换为文档,然后可以迭代每个
,更改
dstartime
dEndTime
属性,然后更改子
节点中的任何数字:

const str=`
Batti Gul-Meter Chalu
rajj10.44 ke10.99 rulaya
rajj ke15.94 hansaya
`;
const doc=new DOMParser().parseFromString(str,'text/html');
const halve=num=>Math.round(100*num/2)/100;
const halveAttrib=(节点,名称)=>{
const newVal=halve(node.getAttribute(名称))
node.setAttribute(名称,newVal);
};
doc.queryselectoral('item')。forEach((item)=>{
halveAttrib(项目“dStartTime”);
halveAttrib(项目“dEndTime”);
item.children[0]。textContent=item.children[0]。textContent
.replace(/\d+(\.\d+)/g,num=>halve(num).toFixed(2));
});
const output=doc.body.innerHTML
.替换(/dstartime/g,“dstartime”)
.replace(/dendtime/g,“dendtime”)
.替换(/n3drhythm/g,“n3drhythm”)
.replace(/str3dscenelayoutfile/g,“str3dscenelayoutfile”);

控制台日志(输出)在Javascript中,您可以使用
DOMParser
将字符串转换为文档,然后可以迭代每个
,更改
dstartime
dEndTime
属性,然后更改子
节点中的任何数字:

const str=`
Batti Gul-Meter Chalu
rajj10.44 ke10.99 rulaya
rajj ke15.94 hansaya
`;
const doc=new DOMParser().parseFromString(str,'text/html');
const halve=num=>Math.round(100*num/2)/100;
const halveAttrib=(节点,名称)=>{
const newVal=halve(node.getAttribute(名称))
node.setAttribute(名称,newVal);
};
doc.queryselectoral('item')。forEach((item)=>{
halveAttrib(项目“dStartTime”);
halveAttrib(项目“dEndTime”);
item.children[0]。textContent=item.children[0]。textContent
.replace(/\d+(\.\d+)/g,num=>halve(num).toFixed(2));
});
const output=doc.body.innerHTML
.替换(/dstartime/g,“dstartime”)
.replace(/dendtime/g,“dendtime”)
.替换(/n3drhythm/g,“n3drhythm”)
.replace(/str3dscenelayoutfile/g,“str3dscenelayoutfile”);

控制台日志(输出)这使用DOM解析器在从HTML文件读取HTML的每个部分后写出值和持续时间。我很难访问文本节点,因此不得不绕过我最不满意的地方。这意味着您知道要搜索的值,这意味着您可以使用regex.replace方法对html字符串进行替换。对于dStartTime和dendTime,您可以直接更换outerHTML。除非您将其写回文件,否则将仅替换当前HTMLDocument中的内容。SetAttribute在此实例中不起作用。我不知道为什么我不能访问文本节点,特别是因为我没有源HTMLDocument。如果有人能解决这个问题,那就太好了

item.outerHTML = Replace$(item.outerHTML, "dstarttime=" & Chr$(34) & item.dstarttime & Chr$(34), "dstarttime=" & 666 & Chr$(34)) 'example  666 as replace value. 
vba:

选项显式
公共子GetValues()
'VBE>Tools>References>HTML对象库
将html设置为HTMLDocument
调试。打印“doc1”,vbNewLine
设置html=GetHTMLFileContent(“C:\Users\User\Desktop\test.html”)第一个html文档。信息保存在扩展名为.html的文本文件中
GetItems html
调试。打印“doc2”,vbNewLine
设置html=GetHTMLFileContent(“C:\Users\User\Desktop\test2.html”)第二个html文档。信息保存在扩展名为.html的文本文件中
GetItems html
端接头
公共子GetItems(作为HTMLDocument的ByVal html)
将项目设置为对象、项目设置为对象、计数器设置为长
Set items=html.getElementsByTagName(“项目”)
对于项目中的每个项目
调试。打印“项目”和计数器+1
Dim itemArr()作为字符串

itemArr=Split(html.body.innerHTML,"这使用DOM解析器在从HTML文件中读取HTML的每一部分后写出值和持续时间。我很难访问文本节点,因此不得不绕过我最不满意的方法。这意味着您知道要搜索的值,这意味着您可以使用r替换HTML字符串egex.Replace方法。对于dStartTime和dendTime,您可以直接在outerHTML上进行替换。除非您写回文件,否则此替换仅在当前HTMLDocument中进行。SetAttribute在此实例中不起作用。我不确定为什么无法访问文本节点,尤其是在没有sourc的情况下
Option Explicit
Public Sub GetValues()
    'VBE > Tools > References > HTML Object Library
    Dim html As HTMLDocument
    Debug.Print "doc1", vbNewLine
    Set html = GetHTMLFileContent("C:\Users\User\Desktop\test.html") 'first html document. Info saved in text file with .html extension
    GetItems html
    Debug.Print "doc2", vbNewLine
    Set html = GetHTMLFileContent("C:\Users\User\Desktop\test2.html") 'second html document. Info saved in text file with .html extension
    GetItems html
End Sub
Public Sub GetItems(ByVal html As HTMLDocument)
    Dim items As Object, item As Object, counter As Long
    Set items = html.getElementsByTagName("item")
    For Each item In items
        Debug.Print " item " & counter + 1
        Dim itemArr() As String
        itemArr = Split(html.body.innerHTML, "</ITEM")
        Debug.Print "startTime = " & Round(item.dStartTime, 2), "endTime = " & Round(item.dendTime, 2), "duration : " & Round(item.dendTime - item.dStartTime, 2)
        Debug.Print "Associated text numbers "
        On Error Resume Next
        GetTextAttributeNumbers Split(itemArr(counter), "<TEXT>")(1)
        On Error GoTo 0
        counter = counter + 1
    Next item
End Sub


Public Sub GetTextAttributeNumbers(ByVal inputString As String)
    Dim matches As Object, iMatch As Object

    With CreateObject("vbscript.regexp")
        .Global = True
        .MultiLine = True
        .IgnoreCase = True
        .Pattern = "\d{1,}(\.\d+)?"
        If .TEST(inputString) Then
            Set matches = .Execute(inputString)
            For Each iMatch In matches
                Debug.Print iMatch

            Next iMatch
        End If
    End With
End Sub

Public Function GetHTMLFileContent(ByVal filePath As String) As HTMLDocument
    '"C:\Users\HarrisQ\Desktop\test.html"
    Dim fso As Object, hFile As Object, hString As String, html As New HTMLDocument
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set hFile = fso.OpenTextFile(filePath)

    Do Until hFile.AtEndOfStream
        hString = hFile.ReadAll()
    Loop

    html.body.innerHTML = hString
    Set GetHTMLFileContent = html
End Function