Страницы: 1
RSS
Вычислить формулу из цифр и букв, Преобразовать цифры и буквы в формулу и вычислить результат
 
Здравствуйте.
Подскажите, пожалуйста, как лучше поступить?
Есть таблица, в которой один из столбцов выглядит следующим образом:
1 x 2 x 3 д
4 д
5 х 6 х 7 д
8 х 9 д
10.1 х 11 х 12.2 д
13 х 14.3 д
Можно ли сделать что-то, чтобы не считать каждую ячейку вручную?
 
iLiliya, что такое "д"?
 
pq
 
iLiliya,  С праздником!
Можно UDF написать. Ну можно и макрофункцию ВЫЧИСЛИТЬ() привлечь, но для этого нужно в файле включать поддержку макросов.
 
Цитата
iLiliya написал:
как лучше поступить?
1. приложить пример, в котором понятно что на входе и что на выходе
2. что такое "д"? - действительно вопрос.
По вопросам из тем форума, личку не читаю.
 
Цитата
написал:
что такое "д"?
"д" - это рандомная литера, в данном конкретном случае предполагается "дни"
 
Цитата
написал:
приложить пример, в котором понятно что на входе и что на выходе2. что такое "д"? - действительно вопрос.
Таблица должна выглядеть следующим образом:
столбец 1           столбец 2
1 x 2 x 3 д           6                
4 д                      4
5 х 6 х 7 д           210
8 х 9 д                 72
10.1 х 11 х 12.2 д    1355,42
13 х 14.3 д           185,9

Цифры в ячейке должны быть перемножены. Литера "д" - в данном конкретном случае смысла не несет.  
 
Цитата
написал:
let    f=(x)=>List.Product(List.Transform(g(x){0},h)),    g=(x)=>List.Zip(List.Split(x,2)),h=(y)=>Number.From(y,"en"),    from = Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content],    to = Table.ToList(from,(x)=>f(Text.Split(x{0}," ")))in    to
Спасибо. Буду пробовать
 
Цитата
написал:
С праздником!Можно UDF написать. Ну можно и макрофункцию ВЫЧИСЛИТЬ() привлечь, но для этого нужно в файле включать поддержку макросов.
Взаимно.
Спасибо. Буду что-то придумывать.
 
Формула массива. Хотя, думаю, вполне можно сообразить покороче и без массива.
=PRODUCT(IFERROR(--TRIM(MID(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(A1;"д";);"х";REPT(" ";15));".";MID(1/2;2;1));{1;15;30};15));0>1))
Перевод формулы на русский: ТЫЦ
Изменено: memo - 09.05.2025 22:31:23
 
Код
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
 
=PRODUCT(--TEXT(MID(SUBSTITUTE(TRIM(SUBSTITUTE(SUBSTITUTE(A2;".";MID(1%;2;1));"х";" "));" ";REPT(" ";15));{1;16;32};15);"основной;основной;\1;\1"))

или массивная для старых версий
=PRODUCT(IFERROR(--MID(SUBSTITUTE(TRIM(SUBSTITUTE(SUBSTITUTE(A1;".";MID(1%;2;1));"х";" "));" ";REPT(" ";15));{1;16;32};15);1))
По вопросам из тем форума, личку не читаю.
 
Всем огромное спасибо.  
 
Вариант
Код
=ПРОИЗВЕД(--ФИЛЬТР.XML("<r><i>"&ПОДСТАВИТЬ(ПОДСТАВИТЬ(ПОДСТАВИТЬ(A1;"д";"");"х";"</i><i>");".";",")&"</i></r>";"//i"))
Согласие есть продукт при полном непротивлении сторон
 
почти тоже самое:
=ПРОИЗВЕД(ФИЛЬТР.XML("<I><i>"&ПОДСТАВИТЬ(ПОДСТАВИТЬ(ПОДСТАВИТЬ(A1;".";ПСТР(8%;2;1));"д";"</i></I>");"х";"</i><i>");"//i"))
...и вместо A1 ,если надо, подставить во всех решениях выше ПОДСТАВИТЬ(A1;"x";"х") (а по примеру буковки то разные)
можно просто:
формула
или
=ПРОИЗВЕД(--ПСТР(ПОДСТАВИТЬ(ПОДСТАВИТЬ(A1;".";ПСТР(8%;2;1))&" 1 х 1";" ";ПОВТОР(" ";99));{1:199:397};99))
 
Ну я бы писал что то вроде такой UDF -ки...
Код
Public Function pos4itat(txt As String) As Variant
Dim rez As String:  rez = ""
Dim i As Long
On Error GoTo ErrHandl
For i = 1 To Len(txt)
    simv = Mid(txt, i, 1)
    If simv Like "[0-9,x,х,.,*,chr(44)]" Then
        If simv = "х" Or simv = "x" Then simv = "*"
        If simv = "," Then simv = "."
        rez = rez & simv
    End If
Next i
pos4itat = Evaluate(rez): Exit Function
ErrHandl: pos4itat = "Ошибка исходных данных."
End Function
Изменено: tutochkin - 10.05.2025 13:55:14 (х и x это две разные х... :))
 
Цитата
написал:
ВариантКод ? 1=ПРОИЗВЕД(--ФИЛЬТР.XML("  "&ПОДСТАВИТЬ(ПОДСТАВИТЬ(ПОДСТАВИТЬ(A1;"д";"");"х";"  ");".";",")&"  ";"//i"))
Спасибо!
 
Цитата
написал:
почти тоже самое:=ПРОИЗВЕД(ФИЛЬТР.XML("  "&ПОДСТАВИТЬ(ПОДСТАВИТЬ(ПОДСТАВИТЬ(A1;".";ПСТР(8%;2;1));"д";"  ");"х";"  ");"//i"))...и вместо A1 ,если надо, подставить во всех решениях выше ПОДСТАВИТЬ(A1;"x";"х")  (а по примеру буковки то разные)можно просто:формула=ПОДСТАВИТЬ(ЛЕВБ(A1;ПОИСК(" ";A1&" "));".";ПСТР(8%;2;1))*ПОДСТАВИТЬ(ПСТР(ЛЕВБ(A1&" 1 ";ПОИСК("#";ПОДСТАВИТЬ(A1&" 1 ";" ";"#";3)));ПОИСК(" ";A1)+2;99);".";ПСТР(8%;2;1))*ПОДСТАВИТЬ(ПСТР(ЛЕВБ(A1&" 1 х 1 ";ПОИСК("#";ПОДСТАВИТЬ(A1&" 1 х 1 ";" ";"#";5)));ПОИСК("#";ПОДСТАВИТЬ(A1&" 1 ";" ";"#";3))+2;99);".";ПСТР(8%;2;1)) или=ПРОИЗВЕД(--ПСТР(ПОДСТАВИТЬ(ПОДСТАВИТЬ(A1;".";ПСТР(8%;2;1))&" 1 х 1";" ";ПОВТОР(" ";99));{1:199:397};99))
Спасибо!
 
Цитата
написал:
Ну я бы писал что то вроде такой UDF -ки...Код ? 123456789101112131415Public Function pos4itat(txt As String) As VariantDim rez As String:  rez = ""Dim i As LongOn Error GoTo ErrHandlFor i = 1 To Len(txt)    simv = Mid(txt, i, 1)    If simv Like "[0-9,x,х,.,*,chr(44)]" Then        If simv = "х" Or simv = "x" Then simv = "*"        If simv = "," Then simv = "."        rez = rez & simv    End IfNext ipos4itat = Evaluate(rez): Exit FunctionErrHandl: pos4itat = "Ошибка исходных данных."End Function
Ого! Спасибо.
Страницы: 1
Читают тему
Наверх