【发布时间】:2018-07-12 20:49:51
【问题描述】:
我制作了一个简单的 VBA 宏,我针对在 excel 中打开的 CSV 文件运行该宏。此宏格式化工作表、删除某些数据、插入列等。然后它将正确格式化的 CSV 复制到服务器,在该服务器上将数据导入到我们的 ERP 中。 CSV 文件是物料清单,一切正常。我想知道它是否可以简化。当我将此宏作为 excel 插件导入时,它不是显示一个宏,而是显示宏中的所有各种子例程,以及按我需要它们运行的顺序调用所有其他子程序的主子程序。有没有更好的方法来安排这段代码?
Sub ProcessBOM()
Call DeleteColumn
Call DelBinFill
Call DelBlankRows
Call Insert3Columns
Call DelRow1
Call ClearColumns
Call InsertProjectName
Call InsertLineItemNo
Call InsertEA
Call MoveColumn
Call InsertDate
Call GetUserName
Call SaveAs
Call MessageBox
End Sub
'Delete first column
Sub DeleteColumn()
Columns(1).EntireColumn.Delete
End Sub
'Delete rows containing BIN FILL
Sub DelBinFill()
Dim i As Integer
For i = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1
If Cells(i, 1) = "BIN FILL" Then Cells(i, 1).EntireRow.Delete
Next i
End Sub
'Delete rows with blank RDI Item #
Sub DelBlankRows()
Dim i As Integer
For i = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1
If Cells(i, 1) = "" Then Cells(i, 1).EntireRow.Delete
Next i
End Sub
'Insert 3 blank columns
Sub Insert3Columns()
Range("A:C").EntireColumn.Insert
End Sub
'Delete Row 1
Sub DelRow1()
Rows(1).EntireRow.Delete
End Sub
'Clear Contents of specified columns
Sub ClearColumns()
Range("E:G").EntireColumn.Clear
End Sub
'Grabs Project Name from Active Sheet and inserts to last row
Sub InsertProjectName()
Dim LastRow As Long
LastRow = Range("D" & Rows.Count).End(xlUp).Row
Range("C1:C" & LastRow) = ActiveSheet.Name
End Sub
'Insert Line Item Numbers
Sub InsertLineItemNo()
ActiveCell.FormulaR1C1 = "1"
LastRow = Range("D" & Rows.Count).End(xlUp).Row
Selection.AutoFill Destination:=Range("A1:A" & LastRow), Type:=xlFillSeries
End Sub
'Insert EA Into Column E
Sub InsertEA()
LastRow = Range("D" & Rows.Count).End(xlUp).Row
Range("E1:E" & LastRow) = "EA"
End Sub
' Moves QTY Data from H to F
Sub MoveColumn()
Columns("H:H").Select
Selection.Cut Destination:=Columns("F:F")
Columns("F:F").Select
End Sub
'Insert Date Into Column G
Sub InsertDate()
Dim LDate As String
LDate = Date
LastRow = Range("D" & Rows.Count).End(xlUp).Row
Range("G1:G" & LastRow).Resize(, 2) = Array(Date, "=""""")
End Sub
'Get logged on username and insert into Column B
Sub GetUserName()
Dim strName As String
strName = Environ("UserName")
LastRow = Range("D" & Rows.Count).End(xlUp).Row
Range("B1:B" & LastRow) = strName
End Sub
'Save file
Sub SaveAs()
Application.DisplayAlerts = False
MyName = ActiveSheet.Name
ActiveWorkbook.SaveAs Filename:="\\navapp1svr\boms$\solidworks\inbound" & "\" & MyName & ".csv", FileFormat:=xlText
ActiveWorkbook.Saved = True
ActiveWorkbook.Close SaveChanges:=False
End Sub
'Prompt the user to verify data upload in Microsoft Dynamics NAV
Sub MessageBox()
MsgBox ("BOM upload complete. Please check Dynamics for accuracy.")
End Sub
【问题讨论】:
-
InsertLineItemNo毫无意义。您如何知道程序中此时的“ActiveCell”或“Selected”范围是什么。那是有风险的生意。 -
你在其他地方调用这些子程序吗?如果不是这样,这似乎被过度重构了,并且使您的代码很难遵循。
-
例如,您必须一遍又一遍地重新计算
LastRow,即使它永远不会改变。为什么不在您的主子程序中执行此操作并将其作为参数传递给这些其他子程序?或者只是删除子例程,然后将所有这些逐步的 rinky dink 逻辑作为一个例程执行。 -
在
InsertDate中声明并设置LDate但从不使用它。 -
对于像
DelBinFill这样的例程,我将创建一个参数来定义要查找的字符串(在这种情况下,它是“BIN FILL”)。这样,您可能会在某个时候重用该例程和/或更轻松地更改要比较的值。DeleteColumn之类的东西也一样——将列号作为参数。我同意@JNevill 的观点,它似乎被过度重构了,但同时你需要继续做你正在做的事情。您将了解自己在编码和维护自己的代码方面的风格和平衡。