Я пришел к тому же выводу, что и Фог, но в другом направлении. Ниже я работаю с вашим кодом, предлагающим изменения, но мне трудно поверить, что вы могли бы сделать эту работу.
Точка 1
У вас есть несколько открытых книг? Вы переключаетесь между ними перед запуском макроса? Предположим, у вас открыто три рабочие книги (A, B и C). Предположим также, что этот макрос и счета находятся в рабочей книге A. Если вы используете рабочую книгу C при запуске макроса, C будет ActiveWorkBook. Можно запускать макросы в нескольких книгах, но это добавляет сложности, без которой, я полагаю, можно обойтись. Если при запуске макроса открыта только одна рабочая книга, ActiveWorkbook.
.
не требуется.
Точка 2
Мне не нравится использовать On Error
для ошибок, которых я могу избежать. Это, вероятно, не важно, но удалить что-то, а затем воссоздать это, кажется мне неправильным. Я бы сделал это так:
Dim DestSh as Worksheet
Dim Found As Boolean
Dim InxWS As Integer
Found = False
For InxWS = 1 To Worksheets.Count
If Worksheets(InxWS).Name = "Printing" Then
Found = True
' Use whichever of the following two statements is most appropriate
' This completely deletes the contents of the worksheet
Worksheets(InxWS).Cells.EntireRow.Delete
' This deletes the contents of the worksheet but keeps the column widths
Worksheets(InxWS).Cells.EntireRow.ClearContents
Exit For
End If
Next
If Not Found Then
Set DestSh = Worksheets.Add
DestSh.Name = "Printing"
End If
Точка 3
Не вижу ничего плохого в следующем:
For Each sh In Worksheets
If sh.Name <> DestSh.Name Then
End If
Next
For Each
- это очень хороший способ работы с таблицами.
Вам нужен какой-то метод проверки, не проверяете ли вы лист «Печать». Однако, если конечный лист всегда будет «Печать», я мог бы написать sh.Name <> "Printing"
.
С другой стороны, если бы я хотел похвастаться, я бы написал:
Const DestShName as String = "Printing"
: :
DestSh.Name = DestShName
: :
If sh.Name <> DestShName Then
С помощью этого кода я мог бы изменить имя листа назначения, изменив выражение Const (константа).
Точка 4
Рассмотрим:
Worksheets(wks.Name).Range("C6:E6").Value
Что такое wks
? Переменная для sh
?
Я думаю, у вас нет Option Explicit
в качестве первой строки вашего модуля. Option Explicit
говорит, что вы хотите запретить использование необъявленных переменных.
Worksheets(sh.Name)
совпадает с sh
.
Я предполагаю, что "C6: E6" были объединены. Если вы хотите значение объединенной области, используйте верхнюю левую ячейку. Итак Range("C6").Value
.
Ваш выбранный случай будет в форме:
With sh
Select Case .Range("C6").Value
Case "Printing"
' Do something
Case "Cleaning"
' Do something
Case "Stationary"
' Do something
Case "Books"
: :
Case Else
' Do something about an unknown supply type
End Select
End With
Точка 5
Если я правильно понял, у вас есть 14 типов поставок, каждый со своим листом назначения. Вам понадобится Select Case
в цикле, чтобы подготовить листы назначения. Тип поставки совпадает с названием листа? Если нет, то это будет очень грязно, особенно если вы добавите другой тип поставки.
Возможно, стоит подумать о массивах.
Dim InxShST as Integer
Dim SheetNameList() as String
Dim SupplyTypeList() as String
SheetNameList = Array("Print", "Clean", "Stat", ... )
SupplyTypeList = Array("Printing supplies", "Cleaning supplies", ... )
При одинаковом порядке названий листов и типов поставки вы можете найти тип поставки в заказе на поставку и преобразовать его в имя листа. Если вы добавляете новый тип поставки, просто добавьте новое значение в конец каждого массива.
Вернемся к пункту 2. Я предлагаю вам забыть о добавлении рабочих листов VBA; создайте 14 листов вручную.
Код становится:
For InxWS = 1 To Worksheets.Count
For InxShST = LBound(SheetNameList) To UBound(SheetNameList)
If Worksheets(InxWS).Name = SheetNameList(InxShST) Then
Worksheets(InxWS).Cells.EntireRow.ClearContents
Exit For
End If
Next
Next
Я признаю, что это сложнее, но готовит столько листов, сколько вам нужно. У вас есть два цикла: один для рабочих листов и один для имен рабочих листов. Когда вы получаете совпадение, у вас есть лист, который необходимо очистить. LBound
обозначает Нижнюю границу. UBound
обозначает верхнюю границу. Второй For-Loop
подстраивается под размер массива.
Вы можете использовать:
For Each SheetNameCrnt In SheetNameList
Это может выглядеть проще. Но с помощью индекса вы можете связать SheetNameList(InxShST)
с SupplyTypeList(InxShST)
Другие баллы
Вы уверены, что хотите один лист для каждого заказа на покупку? Сколько заказов на покупку у вас есть в день. 10? 100? 500? Это может быть очень неуправляемая рабочая тетрадь.
Из других операторов вашего макроса я предполагаю, что у вас есть фиксированный заголовок, а затем по одной строке данных на каждый заказанный продукт. Вы не определяете природу этих строк, но я предполагаю, что вы хотите скопировать их на соответствующий лист.
Возможно, я мог бы догадаться о структуре этих строк данных, но я должен поставить под сомнение ваш дизайн. Если я закажу у вас картридж для принтера и немного мыльного порошка, нужно ли мне два заказа на покупку? Я не думаю, что вы выиграете мой бизнес.