Код |
---|
Option Explicit Sub CalculateProductFromFormattedString() ' --- Константы --- ' Имя листа, на котором находится столбец с данными Const TargetSheetName As String = "Лист1" ' <--- ИЗМЕНИТЕ НА ИМЯ ВАШЕГО ЛИСТА (например, "Данные") ' Диапазон ячеек с исходными данными (столбец, например, "A1:A10" или "B2:B100") Const DataRangeAddress As String = "A1:A10" ' <--- ИЗМЕНИТЕ НА НУЖНЫЙ ДИАПАЗОН С ВАШИМИ ДАННЫМИ ' Диапазон ячеек для записи результатов (произведения). ' Может быть тот же столбец, если вы хотите заменить исходные данные результатом, ' или другой столбец (например, "B1:B10"), куда будут записаны результаты. ' Убедитесь, что размер и количество ячеек в диапазоне результатов соответствует диапазону данных. Const ResultRangeAddress As String = "B1:B10" ' <--- ИЗМЕНИТЕ НА ДИАПАЗОН ДЛЯ ЗАПИСИ РЕЗУЛЬТАТОВ ' --- Переменные --- Dim ws As Worksheet ' Объект листа Excel Dim dataRng As Range ' Объект диапазона с исходными данными Dim resultRng As Range ' Объект диапазона для записи результатов Dim dataCell As Range ' Объект для перебора каждой ячейки в диапазоне данных Dim resultCell As Range ' Объект для записи результата в соответствующую ячейку Dim cellValue As Variant ' Значение, прочитанное из ячейки (может быть пустым) Dim cellText As String ' Значение ячейки как строка для обработки Dim cleanedText As String ' Строка после удаления лишних символов (" д") Dim numbersArray() As String ' Массив строк с числами после разделения Dim product As Double ' Переменная для хранения произведения чисел Dim numStr As Variant ' Переменная для перебора элементов массива чисел (как строк) Dim numValue As Double ' Переменная для хранения числового значения после преобразования Dim i As Long ' Счетчик для синхронизации ячеек в диапазонах данных и результатов ' --- Настройка --- ' Включаем обработку ошибок. Если произойдет ошибка, выполнение перейдет к метке ErrorHandler. On Error GoTo ErrorHandler ' Отключаем обновление экрана для ускорения работы макроса на больших диапазонах. Application.ScreenUpdating = False ' Возможно, потребуется отключить автоматический пересчет, если у вас много формул. ' Application.Calculation = xlCalculationManual ' --- Получение объектов листа и диапазонов --- ' Временно отключаем обработку ошибок, чтобы проверить существование листа и диапазонов On Error Resume Next Set ws = ThisWorkbook.Sheets(TargetSheetName) Set dataRng = ws.Range(DataRangeAddress) Set resultRng = ws.Range(ResultRangeAddress) ' Получаем диапазон для результатов ' Восстанавливаем стандартную обработку ошибок On Error GoTo ErrorHandler ' Проверяем, найдены ли лист и диапазоны If ws Is Nothing Then MsgBox "Ошибка: Лист с именем """ & TargetSheetName & """ не найден.", vbCritical GoTo ExitMacro End If If dataRng Is Nothing Then MsgBox "Ошибка: Некорректный адрес диапазона данных """ & DataRangeAddress & """ на листе """ & TargetSheetName & """.", vbCritical GoTo ExitMacro End If If resultRng Is Nothing Then MsgBox "Ошибка: Некорректный адрес диапазона результатов """ & ResultRangeAddress & """ на листе """ & TargetSheetName & """.", vbCritical GoTo ExitMacro End If ' Проверяем, что количество ячеек в диапазонах данных и результатов совпадает If dataRng.Cells.Count <> resultRng.Cells.Count Then MsgBox "Ошибка: Количество ячеек в диапазоне данных (" & dataRng.Address(False, False) & ") " & _ "и диапазоне результатов (" & resultRng.Address(False, False) & ") не совпадает." & vbCrLf & _ "Эти диапазоны должны иметь одинаковый размер (например, A1:A10 и B1:B10, или A1:A10 и A1:A10).", vbCritical GoTo ExitMacro End If ' --- Обработка каждой ячейки в диапазоне данных --- i = 1 ' Инициализируем счетчик для доступа к соответствующей ячейке в диапазоне результатов For Each dataCell In dataRng.Cells ' Определяем соответствующую ячейку в диапазоне результатов Set resultCell = resultRng.Cells(i) ' Читаем значение из текущей ячейки данных cellValue = dataCell.Value ' Проверяем, пуста ли ячейка или содержит ошибку If IsEmpty(cellValue) Or IsError(cellValue) Then resultCell.Value = cellValue ' Копируем пустоту или ошибку в ячейку результата i = i + 1 GoTo NextCell ' Переходим к следующей ячейке данных End If ' Преобразуем значение в текст и убираем лишние пробелы по краям cellText = Trim(CStr(cellValue)) ' Проверяем, не стала ли строка пустой после Trim If cellText = "" Then resultCell.Value = "" ' Если пустая строка, оставляем ячейку результата пустой i = i + 1 GoTo NextCell End If ' --- Очистка строки от лишних символов --- ' Удаляем " д" (пробел + "д"). Важно удалить пробел перед "д". cleanedText = Replace(cellText, " д", "") ' Также удаляем просто "д", если вдруг нет пробела перед ней cleanedText = Replace(cleanedText, "д", "") ' Удаляем возможные лишние пробелы в начале или конце после удаления "д" cleanedText = Trim(cleanedText) ' --- Разделение строки на отдельные числа --- ' Разделяем очищенную строку на массив строк, используя " x " как разделитель. ' Split("1 x 2 x 3", " x ") вернет массив: {"1", "2", "3"} ' Split("4", " x ") вернет массив: {"4"} numbersArray = Split(cleanedText, " x ") ' --- Вычисление произведения --- product = 1 ' Инициализируем произведение единицей (чтобы первое число умножилось на 1) Dim conversionError As Boolean ' Флаг для отслеживания ошибок преобразования ' Перебираем каждую строку-число в полученном массиве For Each numStr In numbersArray ' Убираем лишние пробелы из текущей строки-числа numStr = Trim(CStr(numStr)) ' Убедимся, что это строка перед Trim ' Проверяем, не пустая ли строка после Trim (может быть при двойном разделителе " x x ") If numStr <> "" Then ' Пытаемся преобразовать строку в число (Double для поддержки десятичных) On Error Resume Next ' Временно игнорируем ошибку при преобразовании в число numValue = CDbl(numStr) On Error GoTo ErrorHandler ' Восстанавливаем стандартную обработку ошибок ' Проверяем, была ли ошибка преобразования (например, если в строке не число) If Err.Number <> 0 Then ' Если произошла ошибка при преобразовании, помечаем флаг и выходим из внутреннего цикла conversionError = True Exit For End If ' Умножаем текущее число на текущее произведение product = product * numValue End If Next numStr ' Переходим к следующему элементу в массиве чисел ' --- Запись результата --- ' Проверяем, не было ли ошибок при преобразовании чисел If conversionError Then ' Если была ошибка преобразования, записываем сообщение об ошибке в ячейку результата resultCell.Value = "Ошибка данных: " & cleanedText Else ' Если ошибок не было, записываем вычисленное произведение resultCell.Value = product End If NextCell: ' Метка для перехода к следующей ячейке данных в цикле For Each i = i + 1 ' Увеличиваем счетчик ячеек Next dataCell ' Переходим к следующей ячейке в диапазоне данных ' --- Сообщение об успешном завершении --- MsgBox "Расчеты завершены.", vbInformation ExitMacro: ' --- Секция завершения макроса (выполняется всегда при выходе, включая ошибки) --- ' Включаем обратно обновление экрана Application.ScreenUpdating = True ' Если отключали автоматический пересчет, включаем его обратно ' If Application.Calculation = xlCalculationManual Then Application.Calculation = xlCalculationAutomatic ' Очищаем используемые объекты Set ws = Nothing Set dataRng = Nothing Set resultRng = Nothing Set dataCell = Nothing Set resultCell = Nothing Exit Sub ' Завершаем выполнение макроса ErrorHandler: ' --- Обработчик ошибок --- ' Если произошла непредвиденная ошибка MsgBox "Произошла ошибка № " & Err.Number & ": " & Err.Description & vbCrLf & _ "Макрос будет завершен." & vbCrLf & _ "При обработке ячейки: " & dataCell.Address(False, False) & vbCrLf & _ "Исходное значение: """ & cellValue & """", vbCritical Resume ExitMacro ' Переходим к секции завершения для корректного выхода End Sub |
One tap - one kill