powered by simpleCommunicator - 2.0.48     © 2025 Programmizd 02
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Несложный код, но долго работает
7 сообщений из 7, страница 1 из 1
Несложный код, но долго работает
    #38453861
КД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Следующий код вроде бы несложен: с листов копируются диапазоны и вставляются на лист сводной таблицы.
Но работает долго. Одно узкое место нашел, но что с ним поделать - не знаю. Может быть, ещё что-то можно поменять?
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
Public Sub Forming_Svodnaia_Table()
Dim strWorkbookName As String
Dim xlWorkbook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim rng As Range
Dim lngRow As Long
Dim intNumberProb As Integer
Dim lngBeginIngredientRow As Long
Dim lngRowInSvod_Tabl As Long
Dim lngBeginNextIngredientRow As Long
Dim lngNumberFreeRow As Long
Dim intCountSheets As Integer
Dim lngEndHeadIngredientRow As Long
Dim lngHeadIngredientRow As Long
Dim lngRowForIngredient As Long
Dim lngInsertRow As Long
Dim intCountInsert As Integer
Dim blnExitFor As Boolean

On Error GoTo ErrorHandler

    strWorkbookName = ThisWorkbook.Name
    Set xlWorkbook = Application.Workbooks(strWorkbookName)
    Set xlSheet = xlWorkbook.Worksheets("протокол")
    
    'определяем количество проб (на листе 'протокол')
    For lngRow = 9 To 65536
        If Len(xlSheet.Cells(lngRow, 2).Value) = 0 Then
            intNumberProb = xlSheet.Cells(lngRow - 1, 2).Value
            Exit For
        End If
    Next
    
    Application.ScreenUpdating = False
    
    'теперь работаем с листом 'свод_табл'
    Set xlSheet = xlWorkbook.Worksheets("свод_табл")
    xlSheet.Unprotect "1"
    'продвигаемся по первому столбцу и натыкаемся на очередной ингредиент
    blnExitFor = False
    For lngRowInSvod_Tabl = 1 To 65536
        
        If xlSheet.Cells(lngRowInSvod_Tabl, 1).Value = "e" Then Exit For  'дошли до ячейки 'e' (end)
        
        If xlSheet.Cells(lngRowInSvod_Tabl, 1).Interior.ColorIndex = 37 Then
            lngBeginIngredientRow = lngRowInSvod_Tabl 'начало очередного ингредиента
            gstrSheetName = xlSheet.Cells(lngRowInSvod_Tabl, 1).Value  'его название
            'узнаем размер блока, который занимает этот ингредиент
            Call SizeBlock(gstrSheetName)
            
            'но поскольку в фотометрических методиках 2 правых столбца не нужны, уменьшим для них значение правой границы на 2
            Select Case gstrSheetName
                Case "NH4 (Ф)", "NO3 (Ф)", "NO2 (Ф)", "PO4 (Ф)", "Fe (Ф)", "Cu (Ф)", "Mn (Ф)", "Cr (Ф)", "SO4 (Тб)"
                    mintColumnsInBlock = mintColumnsInBlock - 2
            End Select
            
            
            'определяем начало следующего за ним ингредиента
            For lngRow = lngBeginIngredientRow + 1 To 65536
                Rem If Len(xlSheet.Cells(lngRow, 1).Value) <> 0 Then 'начало следующего за ним ингредиента
                If xlSheet.Cells(lngRow, 1).Value = "e" Then blnExitFor = True
                
                If xlSheet.Cells(lngRow, 1).Interior.ColorIndex = 37 Or xlSheet.Cells(lngRow, 1).Value = "e" Then 'начало следующего за ним ингредиента
                    lngBeginNextIngredientRow = lngRow
                    Exit For
                End If
            Next
            
            'определяем количество строк до следующего за ним ингредиента
            lngNumberFreeRow = lngBeginNextIngredientRow - lngBeginIngredientRow - 1
            
            'очищаем эти строки, если там что-то есть
            If lngNumberFreeRow > 4 Then
                Set rng = xlSheet.Range(xlSheet.Cells(lngBeginIngredientRow + 1, 1), xlSheet.Cells(lngBeginNextIngredientRow - 4, 256))
                rng.Delete shift:=xlUp
                'переопределяем значение числа свободных строк
                lngNumberFreeRow = lngBeginNextIngredientRow - lngBeginIngredientRow - lngNumberFreeRow + 2
            End If
            
           
            'теперь работаем с конкретным листом
            Set xlSheet = xlWorkbook.Worksheets(gstrSheetName)
            
            'определяем количество строк, занимаемое "шапкой" (от 2 строки до строки, где находится № п/п пробы = 1)
            For lngRow = 2 To 65536
                If xlSheet.Cells(lngRow, 2).Value = 1 Then
                    lngEndHeadIngredientRow = lngRow
                    Exit For
                End If
            Next
            
            lngHeadIngredientRow = lngEndHeadIngredientRow - 2  'количество строк, занимаемое "шапкой"
            lngRowForIngredient = lngHeadIngredientRow + (mintRowsInBlock + 1) * intNumberProb 'число строк, требуемое для размещения ингредиента
            
            'вычисляем сколько строк требуется воткнуть
            lngInsertRow = lngRowForIngredient - lngNumberFreeRow
                                
            'возвращаемся на сводную таблицу и втыкаем нужное количество строк в нужное место
            Set xlSheet = xlWorkbook.Worksheets("свод_табл")
            
            For intCountInsert = 1 To lngInsertRow + 6 'втыкать будем столько раз, сколько недостает строк (+ 6 - на отступ)
                'выделяем строку и вставляем строку перед ней
                Set rng = xlSheet.Range(xlSheet.Cells(lngBeginIngredientRow + 2, 1), xlSheet.Cells(lngBeginIngredientRow + 2, 256))
                rng.Cells.Copy
                rng.Cells.Insert shift:=xlDown  'ВОТ ЭТО - УЗКОЕ МЕСТО

            Next
            
            
            'место подготовлено - можно копировать
            Set xlSheet = xlWorkbook.Worksheets(gstrSheetName)
            
            Set rng = xlSheet.Range(xlSheet.Cells(2, 1), xlSheet.Cells(lngRowForIngredient + 1, mintColumnsInBlock))  'выделяем все, что
                                                                                                    'занимает ингредиент на своем листе
            rng.Cells.Copy  'копируем
            
            
            Set xlSheet = xlWorkbook.Worksheets("свод_табл")
            
            Set rng = xlSheet.Range(xlSheet.Cells(lngBeginIngredientRow + 2, 1), _
                xlSheet.Cells(lngBeginIngredientRow + lngRowForIngredient + 1, mintColumnsInBlock)) 'выделяем место для копирования
            rng.Cells.Insert shift:=xlShiftToRight   'вставляем в него скопированное
            
            'но теперь удалим ячейки, из-за которых сдвинулся столбец сортировки
            Set rng = xlSheet.Range(xlSheet.Cells(lngBeginIngredientRow + 2, mintColumnsInBlock + 1), _
                xlSheet.Cells(lngBeginIngredientRow + lngRowForIngredient + 1, mintColumnsInBlock * 2))
            rng.Cells.Delete shift:=xlShiftToLeft
            
            Rem rng.Columns.AutoFit
            
            xlSheet.Range(xlSheet.Cells(lngBeginIngredientRow + 2, 1), _
                xlSheet.Cells(lngBeginIngredientRow + lngRowForIngredient + 1, mintColumnsInBlock)).EntireRow.AutoFit   'подгоняем высоту строки под содержимое
            Rem xlSheet.Range(xlSheet.Cells(lngBeginIngredientRow + 2, 1), _
                xlSheet.Cells(lngBeginIngredientRow + lngRowForIngredient + 1, mintColumnsInBlock)).EntireColumn.AutoFit
            Application.CutCopyMode = False 'убираем выделение
            Rem xlsheet.Protect "1"
                        
        End If
        
        If blnExitFor Then Exit For
        
    Next
    
    Application.ScreenUpdating = True
    
ErrorHandlerExit:
    Exit Sub
ErrorHandler:
    Application.ScreenUpdating = True
    MsgBox "Forming_Svodnaia_Table " & gstrSheetName & " Ошибка №:" & Err.Number & ";Описание:" & Err.Description
    Resume ErrorHandlerExit
End Sub
...
Рейтинг: 0 / 0
Несложный код, но долго работает
    #38453954
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, я бы для начала вместо перебора ячеек в цикле (тем более, во вложенном) - воспользовался бы .Find()
Ну и "узкое" место не в использовании .Insert , а в том, что вы используете копирование через буфер. Попробуйте копировать через rng.Copy Destination:=
...
Рейтинг: 0 / 0
Несложный код, но долго работает
    #38454112
КД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Идея понятна, спасибо!
...
Рейтинг: 0 / 0
Несложный код, но долго работает
    #38454210
Кстати, как можно по-быстрому для каждой ячейки столбца сменить текстовые значения типа 18.56 на числовое, чтобы потом в расчетах исп-ть? Циклом по сотне тысяч ячеек наверное не вар-т.
...
Рейтинг: 0 / 0
Несложный код, но долго работает
    #38454217
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если системный разделитель запятая, то простой заменой точки на запятую (при условии, что ячейка имеет формат "общий" или "числовой"
...
Рейтинг: 0 / 0
Несложный код, но долго работает
    #38454248
Shocker.Proесли системный разделитель запятая, то простой заменой точки на запятую (при условии, что ячейка имеет формат "общий" или "числовой"
а если встречается и текстовый формат?
...
Рейтинг: 0 / 0
Несложный код, но долго работает
    #38454441
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
грязный комплектовщик,

Ну так сначала выставить для всего столбца числовой формат ("общий" - не пойдёт, числа могут в даты преобразоваться), а затем произвести замену разделителя.
Ctrl+Space, Ctrl+Shift+!, Ctrl+H - выставить знаки, Заменить всё...
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Несложный код, но долго работает
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]