2016-12-30 33 views
3

我想設計一個VBA腳本,它將從Excel電子表格中將值導出爲CSV文件。這將用於通過單獨的Powershell腳本部署多個虛擬機。處理一個單元格中的多個值以導出爲CSV

目前,Export to CSV操作正在處理每個單元的單個VM名稱以及相應的設置,但是在腳本的實際執行中,我們可能會在單個單元中有多個VM名稱(用逗號分隔),但會正在進行的單元格中的設置相同。

我想知道的是,是否有可能/如何去使那些由逗號分隔的單元格中的值填充單獨的行,但仍然具有CSV文件中相應標題下的設置。

代碼:

Function BuildValuesString(colIndex As String, rows As String) As String 
    Dim val As Variant 

    For Each val In Split(rows, ",") 
     If Cells(val, colIndex) <> "" Then BuildValuesString = BuildValuesString & Cells(val, colIndex).Value & "," 
    Next val 
End Function 
Function BuildNullStrings(numNullStrings As Long) As String 
    Dim iNullStrings As Long 

    For iNullStrings = 1 To numNullStrings 
     BuildNullStrings = BuildNullStrings & "" & "," 
    Next iNullStrings 
End Function 


Sub WriteCSVFile2() 

    Dim My_filenumber As Integer 
    Dim logSTR As String 

    My_filenumber = FreeFile 

    logSTR = logSTR & "Srv. Descr." & "," 
    logSTR = logSTR & "E-mail" & "," 
    logSTR = logSTR & "Env." & "," 
    logSTR = logSTR & "Prot. Level" & "," 
    logSTR = logSTR & "DataC" & "," 
    logSTR = logSTR & "# VMs" & "," 
    logSTR = logSTR & "Name" & "," 
    logSTR = logSTR & "Cluster" & "," 
    logSTR = logSTR & "VLAN" & "," 
    logSTR = logSTR & "NumCPU" & "," 
    logSTR = logSTR & "MemoryGB" & "," 
    logSTR = logSTR & "C_System" & "," 
    logSTR = logSTR & "D_Homevg" & "," 
    logSTR = logSTR & "App_eHealth" & "," 
    logSTR = logSTR & "TotalDisk" & "," 
    logSTR = logSTR & "Datastore" & "," 
    logSTR = logSTR & "Template" & "," 

    logSTR = logSTR & Chr(13) 

    logSTR = logSTR & BuildValuesString("C", "18,19,20,21,22,26,27,28,29,30,31,32,33,34") 
    logSTR = logSTR & TotalIt(Range("C32:C33")) 

    logSTR = logSTR & Chr(13) 

    logSTR = logSTR & BuildNullStrings(5) 
    logSTR = logSTR & BuildValuesString("C", "18,19,20,21,22,37,38,39,40,41,42,43,44,46") 
    logSTR = logSTR & TotalIt(Range("C43:C44")) 

    logSTR = logSTR & Chr(13) 

    logSTR = logSTR & BuildNullStrings(5) 
    logSTR = logSTR & BuildValuesString("C", "18,19,20,21,22,48,49,50,51,52,53,54,55,58") 
    logSTR = logSTR & TotalIt(Range("C54:C55")) 

Open "Z:\Operational Env. Requests\2016\Requests(Test)\" & ThisWorkbook.Name & ".csv" For Append As #My_filenumber 
    Print #My_filenumber, logSTR 
Close #My_filenumber 

End Sub 

Function TotalIt(rng As Range) 
    Dim c, arr, t, rv As Double, v 
    For Each c In rng.Cells 
     If Len(c.Value) > 0 Then 
      arr = Split(c.Value, ",") 
      For Each v In arr 
       If IsNumeric(v) Then rv = rv + v 
      Next v 
      Exit For 
     End If 
    Next c 
    TotalIt = rv 
End Function 

I.E. 如果單元格C:27具有「VM1,VM2,VM3」,則將不同行上的每個值分開,但仍然輸入與其他標題相關聯的值。

目前VBA腳本將輸入的數值爲:

Name   Cluster  VLAN NumCPU  MemoryGB 
VM1    VM2   VM3 VMCluster VLAN1 etc. 

我想它做的是

Name Cluster VLAN 
VM1 VMCluster VLAN1 
VM2 VMCluster VLAN1 
VM3 VMCluster VLAN1 

這完全打亂了排列,如果我試圖執行VBA腳本以其目前的格式。我希望得到一些幫助,以便我能夠實現預期的結果。

謝謝你的任何援助,您可以提供

+1

嗨,看看在[Split函數(https://msdn.microsoft.com/en-us/library/6x627e5f(V = VS.90 ).aspx) - *「返回一個包含指定數量的子串的基於零的一維數組。」*。您可以將其應用於C27,然後檢查它返回的多少個子字符串。相應地修改你的宏。 –

+1

您還應該查看InStr以首先檢查逗號,並創建用於找到或未找到的邏輯:https://msdn.microsoft.com/en-us/library/8460tsh1(v=vs.90)。 aspx – Sorceri

+0

FWIW - 您的'BuildNullStrings(5)'可以替換爲'String(5,「,」)',擺脫功能的需要。 (或者,如果你願意,改變'BuildNullStrings'的內容來簡單地說'BuildNullStrings = String(numNullStrings,「,」)') – YowE3K

回答

2

這是從根本上過於簡單,但基於名稱,在A-C柱集羣和VLAN的你簡單例子,這將採取和輸出分流到CSV。

Sub SplitToCsv() 

    Dim rw, lastRow As Long 
    Dim ws As Worksheet 
    Dim vms, vm, rowData As Variant 

    Set ws = Sheets("Sheet1") 
    lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row 

    Open "C:\test.csv" For Output As #1 

    For rw = 1 To lastRow 
    vms = Split(ws.Cells(rw, 1).Value2, ",") 
    For Each vm In vms 
     Print #1, Join(Array(vm, ws.Cells(rw, 2).Value2, ws.Cells(rw, 3).Value2), ",") 
    Next vm 
    Next rw 

    Close #1 

End Sub 

這將以此爲輸入:

Name   Cluster  VLAN 
VM1,VM2,VM3 VMCluster VLAN1 
VM4   VMCluster2 VLAN2 
VM5,VM6  VMCluster3 VLAN3 

並把它變成看起來像這樣一個文件:

Name,Cluster,VLAN 
VM1,VMCluster,VLAN1 
VM2,VMCluster,VLAN1 
VM3,VMCluster,VLAN1 
VM4,VMCluster2,VLAN2 
VM5,VMCluster3,VLAN3 
VM6,VMCluster3,VLAN3 

- 編輯2017年1月3日 -

我想我現在明白了。這是一個精簡版/重構版本的代碼。我可能是錯的,但我相信是你想要做什麼:

Sub WriteCSVFile2() 

    Dim My_filenumber As Integer 
    Dim header, line As String 
    Dim values, vlan, names As Variant 
    Dim row As Integer 

    My_filenumber = FreeFile 
    Open "c:\cdh\" & ThisWorkbook.Name & ".csv" For Append As #My_filenumber 
    Print #My_filenumber, Join(Array("Srv. Descr.", "E-mail", "Env.", _ 
     "Prot. Level", "DataC", "# VMs", "Name", "Cluster", "VLAN", _ 
     "NumCPU", "MemoryGB", "C_System", "D_Homevg", "App_eHealth", _ 
     "TotalDisk", "Datastore", "Template"), ",") 

    header = Join(Application.Transpose(Range("C18:C22").Value), ",") 

    For row = 26 To 50 Step 12 
     values = Application.Transpose(Range("C" & row & ":C" & row + 8).Value) 
     names = values(2) 
     For Each vlan In Split(names, ",") 
     values(2) = vlan 
     line = Join(values, ",") 
     Print #My_filenumber, header & "," & line 
     Next vlan 
    Next row 

    ' TotalIt(Range("C54:C55")) 

    Close #My_filenumber 

End Sub 

一些注意事項: - 我註釋掉TotalIt只是因爲我認爲它的工作原理,並沒有集中在部分 - 您的代碼查看第26,37,48行,但電子表格實際上具有26,38,50(一個附加行)的引用。我的代碼反映了後者

我認爲如果您添加更多配置選項,較小的代碼庫將更易於調試並希望更具可擴展性。

這裏是我的輸出:

Srv. Descr.,E-mail,Env.,Prot. Level,DataC,# VMs,Name,Cluster,VLAN,... 
Service,Email,Environment,Protection,Data Center,,VM1,VMCluster,VLAN1 etc.,,,,, 
Service,Email,Environment,Protection,Data Center,,VM2,VMCluster,VLAN1 etc.,,,,, 
Service,Email,Environment,Protection,Data Center,,VM3,VMCluster,VLAN1 etc.,,,,, 
+0

感謝您的迴應 - 因爲我從Excel電子表格中提取這些數據並將其導出到CSV文件,所有'名稱','羣集','VLAN'等數據來自C列(在單個單元格中,C:27)。有沒有辦法在您提供的解決方案中指定?名稱,羣集和VLAN最終只能在CSV導出後存在於3個獨立的列中 – NeedToKnowBasis22

+0

您是否有機會上傳電子表格的副本,以便以活色顯示它? – Hambone

+0

我想我現在明白了......我也明白爲什麼我沒有乍一看明白你的代碼在做什麼。現在它是有道理的。我剛剛發佈了一個更新,希望能夠大大簡化。讓我知道,如果它不工作或沒有意義 – Hambone

相關問題