Макрос на поиск, вычисление и вывод в результат в ячейку (решено)

Автор Sledo, 19 декабря 2017, 16:44

0 Пользователи и 1 гость просматривают эту тему.

Sledo

Что то ни как не въеду в синтаксис местных макросов.
Задача стоит следующая - есть таблица с данными, по этой таблице надо пройтись с поиском слова "цена", из соседней от нее ячейки взять значение, заменить в ней точку на запятую, произвести вычисление - перемножение десяти чисел из десяти других ячеек, записать наилучший результат в через одну ячейку от найденного слова "цена" и так до тех пор пока не кончится таблица.

JohnSUN

Добро пожаловать на форум!
Давай въезжать вместе.
Покажи примерный лист с данными - подумаем о коде
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Sledo

#2
Думаю что формат будет примерно следующим -
Скин Sawed-Off | Моррис   
Sawed-Off | Моррис
Цена от: 5.28 руб
Скин AUG | Квадрант   
AUG | Квадрант
Цена от: 5.87 руб

Соответственно разделение по символу ":" и новой строке. Да, и тут еще надо убрать будет из ячейки "руб" что бы получить корректное число.
В целом мне пока не ясно куда именно вставлять циклы и ifы

JohnSUN

Понятно... И перемножаемые десять ячеек с наилучшим результатом здесь где?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Sledo

Цитата: JohnSUN от 19 декабря 2017, 17:21
Понятно... И перемножаемые десять ячеек с наилучшим результатом здесь где?
Дело в том что я пока точно не знаю как именно будет выглядеть таблица, что бы ее полностью приводить для заточенного именно под нее решение.
В целом тут есть все что нужно, просто значений вместо 10, только два. Что то тут макросы по синтаксису весьма отличаются от обычных языков программирования.
Сейчас подумал и все оказалось намного сложнее и в то же время проще. Перемножать не нужно, просто значения умножить на 10 и вывести разницу.

Вид таблицы скорее всего будет следующим:
Скин Sawed-Off | Моррис                      разделитель
Sawed-Off | Моррис      
Цена от                             5.28 руб   
Скин AUG | Квадрант      
AUG | Квадрант      
Цена от                             5.87 руб   
Скин G3SG1 | Следопыт                       разделитель
G3SG1 | Следопыт      
Цена от                             5.28 руб   
Скин Glock-18 | Пришелец      
Glock-18 | Пришелец      
Цена от                             14.09 руб   


Логика следующая:
Попробую изобразить в виде С# (конечно код не чистый, ибо браузер его конечно не проверит)

В цикле топаем по ячейкам A вниз, поскольку именно они скорее всего будут являться событием к окончанию цикла
string namberCell = "А";
string nameInCell;
int cellNumber = 0;
while ( true)
{
    //запускаем счетчик
    cellNumber++;

    //добавляем его к букве что бы получился номер ячейки
    namberCell += cellNumber;

    //ставим защиту от зависания
    if(cellNumber > 10000) break;

    //тут берем значение из ячейки namberCell, смотрим не пустая ли она и если пустая то заканчиваем цикл
    if(namberCell != "")
    {
         //смотрим не является ли значение словом "разделение"
         string cellValue = namberCell.доступ к значению ячейки;
         if(cellValue == "разделение")
         {
              //новый счетчик который будет шагать начиная со слова "разделение" доя следующего слова "разделение"
              int counter = cellNumber;

              string workWithValues = "";


              //идем по списку до нового слова "разделение", если тут нет листов (динамического массива). Или вместо всего это создаем динамический массив
              while ( true)
              {
                   workWithValues = "A" + counter;

                   if(workWithValues == "разделение")
                   {
                         //заканчиваем цикл
                         break;
                    }
                   
                   if(cellValue_2 == "цена")
                   {
                          counter ++;
                    }

                    //ставим защиту от зависания
                    if(counter > 10000) break;
               }

              //создаем двумерный массив с которым будем работать по комбинациям, где в первой ячейке будут содержаться номер ячейки, а во второй числовое значение
              float[,] cellValueArray= new float[counter,counter];

               //создаем двумерный массив для лучших значений, где в первой ячейке будут содержаться номер ячейки, а во второй числовое значение
               float[,] bestValuesArray= new float[counter * counter, counter * counter];

              counter = cellNumber;

              for(int i = 0; i < cellValueArray.размер массива; i++)
              {
                   workWithValues += counter;                   

                   //смотрим не является ли значение словом "цена"
                   string cellValue_2 = workWithValues .доступ к значению ячейки;

                   if(cellValue_2 == "цена")
                   {
                       //если да, берем значение соседней ячейки, форматируем его, т.е. заменяем точку на запятую, убираем "руб"
                       //и заносим значение в массив
                       cellValueArray[i,0] = workWithValues ;
                       cellValueArray[i,1] = ячейка с числом;
                       counter ++;
                   }
               }

               counter =0;
               //считаем
               for(int i1 = 0; i1 < 9; i1++)
               {
                     bestValuesArray[i1, 1] = cellValueArray[i1,1] *10;
                     bestValuesArray[i1, 0] = cellValueArray[i1,0];                       
                }

                //теперь надо узнать разницу
              //идем по списку до нового слова "разделение". Создаем новые счетчики

              string workWithValues_2 =  = "A" + counter;
              int counter_3 = counter;

              while ( true)
              {
                   workWithValues += counter;

                   if(workWithValues == "разделение")
                   {
                         //заканчиваем цикл
                         break;
                    }
                   
                   if(cellValue_2 == "цена")
                   {
                          string cellValue_3 = workWithValues .доступ к значению ячейки;
                          for(int i = 0; i< bestValuesArray.длина массива; i++)
                          {
                               bestValuesArray[i,1] = bestValuesArray[i,1] - cellValue_3;
                               //записываем значения массива в соседние ячейки от значения цены
                          }
                          counter_3 ++;
                    }

                    //ставим защиту от зависания
                    if(counter > 10000) break;
               }


                //сортируем от большего к меньшему, где большее в начале массива
                for(int i1 = 0; i1 < counter; i1++)
               {
                     for(int i2 = 0; i2 < counter; i2++)
                     {
                          if(bestValuesArray[i1]> bestValuesArray[i2])
                          {
                               bestValuesArray[counter] = cellValueArray[i1] * cellValueArray[i2]
                               counter ++;
                          }
                      }
                }
         }
     }
     else
    {
        break;
     }
}

JohnSUN

Ну, начнем с того, что именно для этой задачи макрос тебе, скорее всего, не нужен - этот подбор наилучшей разницы можно, пожалуй, сделать и формулой. Это в случае, если покажешь реальный лист и объяснишь словами, что именно нужно подсчитать.
А если действительно хочешь освоить местный Бэйсик, то несколько тезисов на будущее:
1. Перебирать ячейки листа по одной - очень медленный процесс. Здесь обычно одним методом листа считывают все значения в массив, обрабатывают и так же одной строкой пишут в лист.
2. Прерывать цикл по условию "ой, нарвались на пустую ячейку" тоже не принято - случайно затесавшаяся "пустышка" поломает весь алгоритм.
3. Менять точку на запятую и специально выбрасывать обозначение денежной единицы тоже не придется. Встроенная функция Val() возьмет строку " 5.87 руб " и сделает из неё 5,87
4. Как здесь записывают циклы For...Next, While...Wend или Do...Loop прочитай в Справке
5. Прежде чем что-то делать с данными здесь всегда нужно сначала до этих данных добраться:
  oSheets = ThisComponent.getSheets() ' Все листы текущей книги
  oSheet = oSheets.getByIndex(0)   ' Первый (нумерация с нуля) лист
  oCellRangeByName = oSheet.getCellRangeByName("A1:B20") ' Диапазон ячеек на листе
  oCellByPosition = oSheet.getCellByPosition(1, 5) ' Отдельная ячейка на листе (колонка, строка)
  sString = oCellByPosition.getString() ' Текст из ячейки
  nValue = oCellByPosition.getValue()  ' Числовое значение той же ячейки

Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Sledo

Цитата: JohnSUN от 19 декабря 2017, 20:21
Ну, начнем с того, что именно для этой задачи макрос тебе, скорее всего, не нужен - этот подбор наилучшей разницы можно, пожалуй, сделать и формулой. Это в случае, если покажешь реальный лист и объяснишь словами, что именно нужно подсчитать.
Вот ориентировочно таблица с данными https://drive.google.com/open?id=1wWhwWBKpuaieV3pRkz3z0nmUKgLwYTTG
Всего строк около 1600, значений около 500. Формула циклична, а там значения разбросаны, потому без дополнительных меток не обойтись.
Конечно если есть возможность сразу работать с массивом, это лучше.
Спасибо, сейчас посмотрим что получится.

JohnSUN

Я так понял, что в этом варианте таблицы ты слово "разделитель" просто вручную воткнул от фонаря?
Просто в прошлом примере у тебя разделитель был в строке с наименованием, а теперь ты их навставлял как раз в те ячейки, где нужен результат вычислений
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

JohnSUN

Ну, с преобразованием цены в число - фокус не сложный.
А вот что из чего вычитать - ты так и не объяснил (а в пошарпанном коде не очень внятно изложено)
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Sledo

Цитата: JohnSUN от 19 декабря 2017, 21:24
Я так понял, что в этом варианте таблицы ты слово "разделитель" просто вручную воткнул от фонаря?
Просто в прошлом примере у тебя разделитель был в строке с наименованием, а теперь ты их навставлял как раз в те ячейки, где нужен результат вычислений
Я же говорю, что вид окончательной таблицы пока не ясен. В принципе разделитель не важно где конкретно стоит, важно что он есть и относительно его необходимо использовать данные из ячеек. Я просто не знаю как еще на пальцах объяснить.
Проходимся по ячейкам, или по массиву не важно, натыкаемся на слово "разделитель" запоминаем где оно, идем дальше и снова натыкаемся на слово "разделитель". Это и есть диапазон чисел которые необходимо умножить на 10. Затем снова идем в низ пока не натыкаемся на очередной разделитель. Так вот между первым и последним разделителем и есть диапазон первичных вычислений, а именно - надо найти разницу между теми числами которые были умножены на 10 и теми которые стоят за вторым по счету разделителем.

А как сделать запись в ячейку?

JohnSUN

Нет, всё ещё как-то мутно... Первая группа у тебя 7 цен, вторая 5, третья 3... Кого домножать, кого не домножать, как вычитать - не ясно.
Попробуй сформулировать иначе, а? Ну, типа, "подобрать скины на сумму вот такую-то, но чтобы купить как можно больше" или как-нибудь похоже - без привязки к алгоритму, просто смысл задачи

Или .setDataArray - шлёпнуть весь сформированный массив значений в диапазон, или .setValue для одиночной ячейки
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Sledo

Цитата: JohnSUN от 19 декабря 2017, 22:12
Нет, всё ещё как-то мутно... Первая группа у тебя 7 цен, вторая 5, третья 3... Кого домножать, кого не домножать, как вычитать - не ясно.
Попробуй сформулировать иначе, а? Ну, типа, "подобрать скины на сумму вот такую-то, но чтобы купить как можно больше" или как-нибудь похоже - без привязки к алгоритму, просто смысл задачи

Или .setDataArray - шлёпнуть весь сформированный массив значений в диапазон, или .setValue для одиночной ячейки
В том то и проблема, что все именно так не однозначно, почему и приходится писать программу. Было бы просто я бы формул поналяпал и спал бы спокойно)
Ну вот первая группа, которая выходит на 7 цен, умножить каждую цену на 10 и затем каждую вычесть из каждой 5 цен следующей группы. Затем возьмется 5 цен, умножится на 10 и вычтится из каждой 3 цен. И так далее.

JohnSUN

Все умноженные вычитаются? В смысле - вычесть сумму из каждой цены второй группы? Или каждую вычесть?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Sledo

Цитата: JohnSUN от 19 декабря 2017, 22:44
Все умноженные вычитаются? В смысле - вычесть сумму из каждой цены второй группы? Или каждую вычесть?
Вот файл для скачивания с формулами. Надо расширение вернуть на ods
https://drive.google.com/open?id=1fcRFjjTwzYIhpBc3QgleOLRj2c78fs3q

JohnSUN

У тебя в 130-ой, 203-ей и 255-ой строках коэффициенты поехали.
Не заморачивайся с Гугл-диском, прикладывай файл прямо к сообщению - не такие и большие у тебя таблицы, эти 30 Кб форум выдержит

Ну, хорошо. Пусть это будет сформулировано так: если обменять десять комплектов нового скина на один старый, то доплата (выручка) составит столько-то...

Ладно. Допустим, для всей таблицы будут подсчитаны все эти разности. А что дальше? В "пошарпанном" коде дело заканчивалось сортировкой этого массива по убыванию. Имелось в виду, что нужно будет выбрать максимум? То есть весь полученный набор не нужен, нужно только одно число?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне