运行 来自 Excel 的 CMD 行列表

Running List of CMD lines from Excel

任何人都可以帮助满足以下要求吗?

需求A:

我想创建一个循环到 运行 CMD 中的命令字符串列表,只要 C 列中有一个非零值。我想我需要为我的变量定义一个变量 i起始行始终相同,然后是 运行 Shell(),从行 i、F 列的相应单元格中拉出命令字符串。而 Cells(i, "C")不是空白,继续,将 i 增加 1.

需求B:

我还想 link 这个宏在一个目录中工作,该目录由一个较早的宏存放在一个单元格中,该宏列出了选定目录中的所有文件。

这是我的,没有任何循环..

Sub Run_Renaming()

    Dim CommandString As Long
    Dim i As Integer
    i = 5

    'Other steps:
        '1 - need to pick up variable (directory of files listed, taken from first macro
        'when doing manually, I opened command, went to correct directory, then pasted
        'the commands. I'm trying to handle pasting the commands. I'm not sure if I need
        'something to open CMD from VBA, then run through the below loop, or add opening
        'CMD and going to the directory in each iteration of the below loop...

        '2 - Need to say - Loop below text if Worksheets("Batch Rename of Files").Cells(i, "C").Value is no blank

         CommandString = Worksheets("Batch Rename of Files").Cells(i, "F").Value
         Call Shell("cmd.exe /S /K" & CommandString, vbNormalFocus)

    'Other steps:
        '3 - need to increase i by 1

        '4 - need to check if C column is blank or not

        '5 - need to end of C column is blank

End Sub

背景:

我正在为朋友创建一个文件重命名工具。他们可以使用 excel,但不能使用编程语言或命令提示符。因此,我不想执行任何步骤,例如建议 创建批处理文件,这会使我朋友的事情变得复杂。

我创建了一个 excel 文件:

Tab 1 - 用于创建新文件名列表的模板 sheet。通过连接多个单元格、添加文件类型并输出到一系列单元格来工作。在为 CMD

创建重命名命令字符串时,将两个 links 切换到此范围

Tab 2 -

Button 1 - Sub rename() 下面。 VBA 列出 C 列中选定目录中的文件

F 列创建一个命令行,该命令行将根据选项卡 1 的输入将文件 A 重命名为文件 B,即 ren "File 1" "A1_B1_C1.xlsx"

Button 2 - 指的是一个重命名宏(上面的要求 1 和 2),它从按钮 1 和 运行s 通过所有重命名命令字符串在该目录中选取所选目录

Sub rename()

    Dim xRow As Long
    Dim xDirect$, xFname$, InitialFoldr$

    InitialFoldr$ = "C:\"

    Worksheets("Batch Rename of Files").Activate
    Worksheets("Batch Rename of Files").Range("C4").Activate

    With Application.FileDialog(msoFileDialogFolderPicker)

        .InitialFileName = Application.DefaultFilePath & "\"
        .Title = "Please select a folder to list Files from"
        .InitialFileName = InitialFoldr$
        .Show

        If .SelectedItems.Count <> 0 Then

            xDirect$ = .SelectedItems(1) & "\"
            xFname$ = Dir(xDirect$, 7)

            Do While xFname$ <> ""
                ActiveCell.Offset(xRow) = xFname$
                xRow = xRow + 1
                xFname$ = Dir
            Loop

        End If

    End With

End Sub

注意事项:

1) 我不完全清楚你的数据等是如何布局的,所以我提供了一种实现你目标的方法,其中涉及我清楚的元素。

2) 老实说,就我个人而言,我会尽可能多地使用数组或字典,而不是在工作表中来回切换。

然而...

根据您的要求大纲和一些粗略准备,我们有:

1) 使用您的宏 rename(重命名为 ListFiles 并进行一些小的调整)将所选文件夹名称写入 Range("A1") in Worksheets("Batch Rename of Files") 并且C 列的文件名。

2) 使用第二个宏 RenameFilesWorksheets("Batch Rename of Files") 的 F 列获取重命名 shell 命令;将这些写到桌面上的批处理文件中;添加一个额外的第一行命令,将工作目录设置为 Range("A1") 中给出的所选文件夹(要求 A)。 shell命令执行.bat文件,完成重命名(需求B)然后有一行删除.bat文件。

我猜这是一种比循环列 F 范围一次执行一个命令更有效的实现目标的方法。

我没有试图以任何进一步的方式优化代码(我已经添加了一些现有的类型化函数。)还有许多其他可以进行的改进,但这是为了帮助您实现您的要求。

让我知道进展如何!

Tab1 布局(Sheet 包含新文件名):

文件布局的批量重命名(Sheet 包含第一个宏和按钮的输出):

文件的工作表批量重命名布局

在名为 ListFiles 的标准模块中:

Option Explicit

Public Sub ListFilesInDirectory()

    Dim xRow As Long
    Dim xDirect$, xFname$, InitialFoldr$ 'type hints not really needed
    Dim wb As Workbook
    Dim wsTab2 As Worksheet

    Set wb = ThisWorkbook
    Set wsTab2 = wb.Worksheets("Batch Rename of Files")

    InitialFoldr$ = "C:\"

    Dim lastRow As Long
    lastRow = wsTab2.Cells(wsTab2.Rows.Count, "C").End(xlUp).Row

    wsTab2.Range("C4:C" & lastRow).ClearContents 'Get rid of any existing file names

    wsTab2.Range("C4").Activate

    With Application.FileDialog(msoFileDialogFolderPicker)

        .InitialFileName = Application.DefaultFilePath & "\"
        .Title = "Please select a folder to list Files from"
        .InitialFileName = InitialFoldr$
        .Show

        If .SelectedItems.Count <> 0 Then

            xDirect$ = .SelectedItems(1) & "\"
            xFname$ = Dir(xDirect$, 7)
            wsTab2.Range("A1") = xDirect$

            Do While xFname$ <> vbNullString
                ActiveCell.Offset(xRow) = xFname$
                xRow = xRow + 1
                xFname$ = Dir
            Loop

        End If

    End With

End Sub

在名为 FileRenaming 的标准模块中:

Option Explicit

Sub RenameFiles()

    Dim fso As New FileSystemObject
    Dim stream As TextStream
    Dim strFile As String
    Dim strPath As String
    Dim strData As Range
    Dim wb As Workbook
    Dim wsTab2 As Worksheet
    Dim currRow As Range

    Set wb = ThisWorkbook
    Set wsTab2 = wb.Worksheets("Batch Rename of Files")

    strPath = wsTab2.Range("A1").Value2

    If strPath = vbNullString Then

        MsgBox "Please ensure that Worksheet Batch Rename of Files has a directory path in cell A1"

    Else

        If Right$(Trim$(strPath), 1) <> "\" Then strPath = strPath & "\"

        strFile = "Rename.bat"

        Dim testString As String
        Dim deskTopPath As String
        deskTopPath = Environ$("USERPROFILE") & "\Desktop" 'get desktop path as this is where .bat file will temporarily be saved

        testString = fso.BuildPath(deskTopPath, strFile) 'Check if .bat already exists and delete

        If Len(Dir(testString)) <> 0 Then 
            SetAttr testString, vbNormal
            Kill testString
        End If

        Set stream = fso.CreateTextFile(deskTopPath & "\" & strFile, True) 'create the .bat file

        Dim lastRow As Long
        lastRow = wsTab2.Cells(wsTab2.Rows.Count, "C").End(xlUp).Row

        Set strData = wsTab2.Range("F4:F" & lastRow) 'Only execute for as many new file names as present in Col C (in place of your until blank requirement)

        stream.Write "CD /D " & strPath & vbCrLf

        For Each currRow In strData.Rows 'populate the .dat file
            stream.Write currRow.Value & vbCrLf
        Next currRow

        stream.Close

        Call Shell(testString, vbNormalFocus)

        Application.Wait (Now + TimeValue("0:00:01"))  'As sometime re-naming doesn't seem to happen without a pause before removing .bat file

        Kill testString

        MsgBox ("Renaming Complete")
    End If
End Sub

工作表批量重命名文件中的按钮代码

Private Sub CommandButton1_Click()

    ListFilesInDirectory

End Sub

Private Sub CommandButton2_Click()
    RenameFiles
End Sub

.bat 文件内容示例:

版本 2

这是一个不同的版本,它使用字典并将参数从一个子程序传递到另一个子程序。因此,这将是一个仅与一个按钮按下操作相关联的宏,即不会有第二个按钮。单个按钮会调用 ListFiles,后者又会调用第二个宏。可能需要您进入工具 > 参考并添加 Microsoft 脚本运行时参考。

假设选项卡 1 的 Col D 中新文件名的数量与在文件夹中找到的文件数量相匹配(根据您获取文件夹中文件的脚本)。我已将过时的类型 references.Shout 移出到 RubberDuck VBA 加载项团队,以便加载项拾取它们。

在一个标准模块中:

Option Explicit

Public Sub ListFiles()

    Dim xDirect As String, xFname As String, InitialFoldr As String
    Dim wb As Workbook
    Dim ws As Worksheet
    Dim dict As New Scripting.Dictionary
    Dim counter As Long

    Set wb = ThisWorkbook
    Set ws = wb.Worksheets("Tab1") 'Worksheet where new file names are

    counter = 4 'row where new file names start

    InitialFoldr = "C:\"

    With Application.FileDialog(msoFileDialogFolderPicker)

        .InitialFileName = Application.DefaultFilePath & "\"
        .Title = "Please select a folder to list Files from"
        .InitialFileName = InitialFoldr
        .Show

        If .SelectedItems.Count <> 0 Then

            xDirect = .SelectedItems(1) & "\"
            xFname = Dir(xDirect, 7)

            Do While xFname <> vbNullString

              If Not dict.Exists(xFname) Then
                  dict.Add xFname, ws.Cells(counter, "D")  'Or which ever column holds new file names. This add to the dictionary the current name and new name
                  counter = counter + 1
                  xFname = Dir
              End If
            Loop

        End If

    End With

    RenameFiles xDirect, dict 'pass directory path and dictionary to renaming sub

End Sub

在另一个标准模块中:

Public Sub RenameFiles(ByVal folderpath As String, ByRef dict As Dictionary)

    Dim fso As New FileSystemObject
    Dim stream As TextStream
    Dim strFile As String
    Dim testString As String
    Dim deskTopPath As String

    strFile = "Rename.bat"
    deskTopPath = Environ$("USERPROFILE") & "\Desktop"
    testString = fso.BuildPath(deskTopPath, strFile)

    'See if .dat file of same name already on desktop and delete (you could overwrite!)
    If Len(Dir(testString)) <> 0 Then
        SetAttr testString, vbNormal
        Kill testString
    End If

    Set stream = fso.CreateTextFile(testString, True)

    stream.Write "CD /D " & folderpath & vbCrLf

    Dim key As Variant

    For Each key In dict.Keys
        stream.Write "Rename " & folderpath & key & " " & dict(key) & vbCrLf 'write out the command instructions to the .dat file
    Next key

    stream.Close

    Call Shell(testString, vbNormalFocus)

    Application.Wait (Now + TimeValue("0:00:01"))  'As sometime re-naming doesn't seem to happen without a pause before removing .bat file

    Kill testString

   ' MsgBox ("Renaming Complete")

End Sub

脚本运行时间参考:

添加运行时间参考

查找桌面路径的其他方法。摘自 Allen Wyatt:

在标准模块中添加以下内容:

Public Function GetDesktop() As String
    Dim oWSHShell As Object

    Set oWSHShell = CreateObject("WScript.Shell")
    GetDesktop = oWSHShell.SpecialFolders("Desktop")
    Set oWSHShell = Nothing
End Function

然后在其余代码中替换 deskTopPath =..... 的任何实例,例如:

deskTopPath = Environ$("USERPROFILE") & "\Desktop"

desktopPath = GetDesktop