• Как лучше всего формировать xlsx в php на 10+ млн ячеек?

    erge
    @erge
    Примус починяю
    Чтобы было быстрее работайте с файлами xl/worksheets/sheet?.xml (внутри zip архива - xlsx файла) напрямую! либо как с XML, либо как с текстом поиск/замена (через регулярки например), хотя... если это чистый файл с нуля, то проще и быстрее генерировать эти файлы с нуля как текст, в этом файле данные в разделе sheetData, см. пример:

    <sheetData>
        <row r="1">
          <c r="A1" t="str">
            <v>Иванов</v>
          </c>
          <c r="B1" t="str">
            <v>Петров</v>
          </c>
          <c r="С1" t="str">
            <v>Сидоров</v>
          </c>
    ...
        </row>
      </sheetData>


    PS: да сохраните любой эксельник в xlsx переименуйте в zip и посмотрите, поймете.

    Либо переходите на связку ... например на Go + пакет Excelize и либо на нем микросервис сделать и соответственно работать, либо бинарник для cmdline и соответственно вызывать его из PHP
    Ответ написан
  • Парсер webhook на bash?

    erge
    @erge
    Примус починяю

    #!/bin/bash
    echo $@

    На выходе пусто


    данные POST запроса не передаются в cgi bash скрипт в виде параметров!
    скорее всего в bash скрипте нужно читать stdin
    например так:

    #!/bin/bash
    read POST_STRING
    echo $POST_STRING
    Ответ написан
    Комментировать
  • Как записать все запросы в одном в sql?

    erge
    @erge
    Примус починяю
    SQlite3 ??
    Методы объекта Cursor SQLite3

    cursor.executescript(sql_script)

    UPDATE:
    либо так например:

    sql_script = """
    CREATE TABLE IF NOT EXISTS information
                      (id INTEGER PRIMARY KEY AUTOINCREMENT,userid INTEGER,money INTEGER,weight INTEGER,sportmode INTEGER);
    CREATE TABLE IF NOT EXISTS task
                      (id INTEGER PRIMARY KEY AUTOINCREMENT,list TEXT, status INTEGER);
    CREATE TABLE IF NOT EXISTS what
                      (mycommands TEXT);
    CREATE TABLE IF NOT EXISTS accounts
                      (login TEXT, password TEXT, token TEXT)
    """
    
    for sql in sql_script.split(";\n"):
      cursor.execute(sql)
    Ответ написан
    Комментировать
  • Какой самый легкий модуль скрипта оплаты для html сайта взять?

    erge
    @erge
    Примус починяю
    Если сайт на HTML/CSS и без телодвижений на этом сайте, то наверно не модуль, а - платежный шлюз? легко "гуглится"... "Crypto Payment Gateways", например - 12 Best Crypto Payment Gateways in 2022
    Да и собственно зачем эти лишние приводы нужны? ведь можно же сделать перевод из кошелька по номеру другого кошелька без каких либо проблем, указывайте просто номера кошельков в разных криптомонетах , ой ну да, надо скопировать номер кошелька, надо самому указать сумму... ну, платежные шлюзы смотрите.
    Ответ написан
    Комментировать
  • Как найти расстояние между двумя отрезками?

    erge
    @erge
    Примус починяю
    тупое решение в лоб - идем в поисковик, и просто тупо пишем: расстояние между отрезками

    вторая же ссылка (ну лично у меня) - Ю2.30. Расстояние между отрезками

    там и описание и решение и код, правда на Си
    берем его и переписываем на Python, получаем:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*- 
    
    import math
    
    def ras (x1, y1, x2, y2, x3, y3):
      ## Если отрезок вертикальный - меняем местами координаты каждой точки.
      if x1==x2:
        x1, y1 = y1, x1
        x2, y2 = y2, x2
        x3, y3 = y3, x3
      k=(y1-y2)/(x1-x2) ## Ищем коэффициенты уравнения прямой, которому принадлежит данный отрезок.
      d=y1-k*x1
      xz=(x3*x2-x3*x1+y2*y3-y1*y3+y1*d-y2*d)/(k*y2-k*y1+x2-x1)
      dl=-1
      if ( xz<=x2 and xz>=x1 ) or ( xz<=x1 and xz>=x2 ):
        dl=math.sqrt((x3-xz)*(x3-xz)+(y3-xz*k-d)*(y3-xz*k-d)) ## Проверим лежит ли основание высоты на отрезке.
      return dl
    
    
    ## Вводим параметры отрезков
    # xa, ya, xb, yb = [1, 1, 2, 2]
    # xc, yc, xd, yd = [2, 1, 3, 0]
    
    xa, ya, xb, yb = [int(s) for s in input().split()]
    xc, yc, xd, yd = [int(s) for s in input().split()]
    
    min=-1
    t=-2
    s=-2
    
    o=(xb-xa)*(-yd+yc)-(yb-ya)*(-xd+xc)
    o1=(xb-xa)*(yc-ya)-(yb-ya)*(xc-xa)
    o2=(-yd+yc)*(xc-xa)-(-xd+xc)*(yc-ya)
    
    if o!=0:
      t=o1/o
      s=o2/o
    
    if (t>=0 and s>=0) and (t<=1 and s<=1):
      min=0 ## Проверим пересекаются ли отрезки.
    else: 
      ## Найдём наименьшую высоту опущенную из конца одного отрезка на другой.
      dl1=ras(xa,ya,xb,yb,xc,yc)
      min=dl1
      dl2=ras(xa,ya,xb,yb,xd,yd)
      if ( dl2<min and dl2!=-1 ) or min==-1 :
        min=dl2
      dl3=ras(xc,yc,xd,yd,xa,ya)
      if ( dl3<min and dl3!=-1 ) or min==-1 :
        min=dl3
      dl4=ras(xc,yc,xd,yd,xb,yb)
      if ( dl4<min and dl4!=-1) or min==-1 :
        min=dl4
      if min==-1 :
        ## В случае, если невозможно опустить высоту найдём минимальное расстояние между точками.
        dl1=math.sqrt((xa-xc)*(xa-xc)+(ya-yc)*(ya-yc))
        min=dl1
        dl2=math.sqrt((xb-xd)*(xb-xd)+(yb-yd)*(yb-yd))
        if dl2<min :
          min=dl2
        dl3=math.sqrt((xb-xc)*(xb-xc)+(yb-yc)*(yb-yc))
        if dl3<min :
          min=dl3
        dl4=math.sqrt((xa-xd)*(xa-xd)+(ya-yd)*(ya-yd))
        if dl4<min :
          min=dl4
    
    print (min)


    PS: ну, .... пробовали?? или нужно на подносе?
    Ответ написан
    Комментировать
  • Как выбрать последнее значение по дате и предыдущее в одной строке?

    erge
    @erge
    Примус починяю
    Вы по всей видимости так и не прочитали и не посмотрели как работает ROW_NUMBER из ответа на предыдущий вопрос !?

    посмотрите вывод запроса с ROW_NUMBER() !
    SELECT
            b.*,
            row_number() OVER (PARTITION BY id ORDER BY balance_date DESC) r
          FROM balance b


    в данном случае row_number() нумерует в разбивке по id по убыванию даты и соответственно, предыдущая запись - с номером 2

    Поэтому необходимо просто выбрать с r = 1 или r =2 соответственно !


    для наглядности вынес подзапрос с row_number в WITH - обобщенное_табличное_выражение

    WITH bal AS (
        SELECT
            b.*,
            row_number() OVER (PARTITION BY id ORDER BY balance_date DESC) r
          FROM balance b
    )
    SELECT id, balance_date, balance FROM bal WHERE r = 1 or r = 2
      ORDER BY id, balance_date desc
    ;


    см. db<>fiddle

    UPDATE:

    Если выводить последнее и предыдущее значение в одной строке, то выбираем каждое подзапросом и объединяем подзапросы через LEFT JOIN (к последнему присоединяем предыдущее) по id. Через LEFT JOIN чтобы из левой таблицы (последние значения) выбирались все строки и присоединялись из правой (предыдущие значения) те строки какие есть, а если нет, то - NULL

    см. ниже:

    WITH
    bal AS (
        SELECT
            b.*,
            row_number() OVER (PARTITION BY id ORDER BY balance_date DESC) r
          FROM balance b
    ),
    last_bal AS (
      SELECT id, balance_date, balance FROM bal WHERE r = 1
    ),
    prev_bal AS (
      SELECT id, balance_date, balance FROM bal WHERE r = 2
    )
    SELECT
        lb.id,
        lb.balance_date AS last_balance_date, lb.balance AS last_balance,
        pb.balance_date AS prev_balance_date, pb.balance AS prev_balance
      FROM last_bal lb
      LEFT JOIN prev_bal pb ON pb.id = lb.id
    ;


    см. db<>fiddle №2
    Ответ написан
  • Как выбрать последнее по дате значение по группе строк?

    erge
    @erge
    Примус починяю
    см. ROW_NUMBER

    SELECT
        id,
        balance_date_start,
        balance_start,
        balance_date_mid,
        balance_mid
      FROM (
        SELECT
            cb.*,
            row_number() OVER (PARTITION BY id ORDER BY balance_date_start DESC) r
          FROM client_balance cb
        ) t
      WHERE r = 1
    ;


    см. пример на db<>fiddle
    Ответ написан
    Комментировать
  • Возможно ли сделать нулевой count при использовании GROUP BY?

    erge
    @erge
    Примус починяю
    1. нужна таблица - календарь, либо сгенерированный набор дат
    2. либо к календарю надо сделать left join вашей таблицы, либо к вашей таблице надо сделать right join календаря.

    SQL join в примерах с описанием

    в результате получится:

    select cal.cal_date, count(person)
      from some_table st
      right join (
      -- генерируем календарь - набор дат
        select *
          from (
            select adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) cal_date
              from
                (select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
                (select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
                (select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
                (select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
                (select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4
          ) v
          where cal_date between '2021-11-01' and '2021-11-30'
      ) cal on cal.cal_date = st.date_field
      group by cal.cal_date


    в MariaDB есть Sequence Storage Engine, но до MariaDB 10.0 , он поставлялся в виде динамической плагина, начиная с MariaDB 10.1 , движок Sequence устанавливается по умолчанию. Используя его можно генерировать список дат (календарь) следующим образом:

    SELECT '2021-11-01' + INTERVAL seq DAY FROM seq_0_to_29;


    а запрос будет соответственно:

    select cal.cal_date, count(person)
      from some_table st
      right join (
      -- генерируем календарь - набор дат
        SELECT '2021-11-01' + INTERVAL seq DAY as cal_date FROM seq_0_to_29
      ) cal on cal.cal_date = st.date_field
      group by cal.cal_date
    ;


    см. пример работы на dbfiddle.uk

    и если person добавить в группировку - пример
    Ответ написан
    Комментировать
  • Выбрать только одну саму свежую строку для поля?

    erge
    @erge
    Примус починяю
    для MySQL 8.0 испльзовать row_number()

    для более ранних версий использовать подзапросы:

    -- For MySQL 8.0
    select FLOW, OTPERIOD, LOG_DATE, LOG_TIME, ENTITY
      from (
        select
          FLOW, OTPERIOD, LOG_DATE, LOG_TIME, ENTITY,
          row_number() over (partition by ENTITY order by LOG_DATE desc, LOG_TIME desc) num
        from test
      ) tt
      where num = 1
    ;
    
    
    -- For MySQL <=8.0
    select t.*
      from test t
      inner join (
        select max(LOG_DATE) LOG_DATE, MAX(LOG_TIME) LOG_TIME, ENTITY
          from test
          group by ENTITY
          having concat(LOG_DATE,' ', LOG_TIME) = max(concat(LOG_DATE,' ', LOG_TIME))
    ) tt on tt.ENTITY = t.ENTITY and tt.LOG_DATE = t.LOG_DATE and tt.LOG_TIME = t.LOG_TIME
    ;
    
    
    -- For MySQL <=8.0
    select *
      from test t
      where concat(LOG_DATE,' ', LOG_TIME) = (
        select max(concat(LOG_DATE,' ', LOG_TIME))
          from test tt
            where tt.ENTITY = t.ENTITY
          group by ENTITY
      )
    ;


    как-то так, см. пример на dbfiddle.uk

    PS: но по последним двум вариантам будет выдаваться несколько записей если в одну секунду по одному и тому же ENTITY пишется несколько записей, надо дальше "колхозить".
    Ответ написан
    3 комментария
  • Как корректно разбить строку на подстроки по разделителю на множестве строк (по датасету)?

    erge
    @erge Автор вопроса
    Примус починяю
    Необходимо использовать LATERAL (inline-представление), как посоветовал Максим Y
    Но, до версии 12С это было типа недокументированной "фичей" и чтобы ее включить необходимо выполнить:
    alter session set events '22829 trace name context forever';


    Попробовал в 11g (на dbfiddle.uk) и сработало!

    https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=3aa5...

    PS: попробовал у себя на 9i и.... тоже сработало! ))

    alter session set events '22829 trace name context forever';
    
    WITH 
      test AS (
    SELECT 'проул.' as code, 'проул.|пр-к|' as str FROM dual UNION
    SELECT 'ул.' as code, 'ул.|улица|ул-ца|' as str FROM dual UNION
    SELECT 'пер.' as code, 'пер.|переулок|' as str FROM dual UNION
    SELECT 'кв-л' as code, 'кв-л|квартал|' as str FROM dual UNION
    SELECT 'линия' as code, 'линия|' as str FROM dual UNION
    SELECT 'парк' as code, 'парк|' as str FROM dual UNION
    SELECT 'рзд' as code, 'рзд|разъезд|' as str FROM dual UNION
    SELECT 'сад' as code, 'Сад|' as str FROM dual UNION
    SELECT 'тракт' as code, 'тракт|' as str FROM dual UNION
    SELECT 'тер' as code, 'тер|территория|' as str FROM dual UNION
    SELECT 'ст' as code, 'ст|станция|' as str FROM dual UNION
    SELECT 'сл' as code, 'сл|слобода|' as str FROM dual UNION
    SELECT 'пр-кт' as code, 'пр.|проспект|пр-кт|' as str FROM dual UNION
    SELECT 'шоссе' as code, 'ш.|шоссе|' as str FROM dual UNION
    SELECT 'пл' as code, 'пл|площадь|пл-дь|' as str FROM dual UNION
    SELECT 'наб.' as code, 'наб.|набережная|наб-ая|' as str FROM dual UNION
    SELECT 'тупик' as code, 'тупик|' as str FROM dual UNION
    SELECT 'мост' as code, 'мост|' as str FROM dual UNION
    SELECT 'пр.' as code, 'проезд|пр.|' as str FROM dual UNION
    SELECT 'блв.' as code, 'блв.|бульвар|' as str FROM dual UNION
    SELECT 'мкн.' as code, 'мкн.|микрорайон|' as str FROM dual UNION
    SELECT 'пос.' as code, 'пос.|посёлок|' as str FROM dual UNION
    SELECT 'овраг' as code, 'овраг|' as str FROM dual UNION
    SELECT 'городок' as code, 'городок|' as str FROM dual
    )
    SELECT t1.code, SUBSTR(t1.str, 
                  DECODE(t2.lvl, 1, 1, INSTR(t1.str, '|', 1, t2.lvl - 1) + 1),
                  INSTR(t1.str, '|', 1, t2.lvl) 
                  - DECODE(t2.lvl, 1, 1, INSTR(t1.str, '|', 1, t2.lvl - 1) + 1))
    FROM test t1,
      LATERAL (SELECT level AS lvl FROM dual
             CONNECT BY NVL(INSTR(t1.str, '|', 1, level), 0) > 0) t2
    ;


    так же есть еще вариант, через преобразование в XML:
    WITH
    str_csv AS (
      SELECT 'проул.' as code, 'проул.|пр-к|' as str FROM dual UNION
      SELECT 'ул.' as code, 'ул.|улица|ул-ца|' as str FROM dual UNION
      SELECT 'пер.' as code, 'пер.|переулок|' as str FROM dual UNION
      SELECT 'кв-л' as code, 'кв-л|квартал|' as str FROM dual UNION
      SELECT 'линия' as code, 'линия|' as str FROM dual UNION
      SELECT 'парк' as code, 'парк|' as str FROM dual UNION
      SELECT 'рзд' as code, 'рзд|разъезд|' as str FROM dual UNION
      SELECT 'сад' as code, 'Сад|' as str FROM dual UNION
      SELECT 'тракт' as code, 'тракт|' as str FROM dual UNION
      SELECT 'тер' as code, 'тер|территория|' as str FROM dual UNION
      SELECT 'ст' as code, 'ст|станция|' as str FROM dual UNION
      SELECT 'сл' as code, 'сл|слобода|' as str FROM dual UNION
      SELECT 'пр-кт' as code, 'пр.|проспект|пр-кт|' as str FROM dual UNION
      SELECT 'шоссе' as code, 'ш.|шоссе|' as str FROM dual UNION
      SELECT 'пл' as code, 'пл|площадь|пл-дь|' as str FROM dual UNION
      SELECT 'наб.' as code, 'наб.|набережная|наб-ая|' as str FROM dual UNION
      SELECT 'тупик' as code, 'тупик|' as str FROM dual UNION
      SELECT 'мост' as code, 'мост|' as str FROM dual UNION
      SELECT 'пр.' as code, 'проезд|пр.|' as str FROM dual UNION
      SELECT 'блв.' as code, 'блв.|бульвар|' as str FROM dual UNION
      SELECT 'мкн.' as code, 'мкн.|микрорайон|' as str FROM dual UNION
      SELECT 'пос.' as code, 'пос.|посёлок|' as str FROM dual UNION
      SELECT 'овраг' as code, 'овраг|' as str FROM dual UNION
      SELECT 'городок' as code, 'городок|' as str FROM dual
    ),
    str_xml AS (
      SELECT code, XMLType('<a><b>'||replace(str, '|','</b><b>')||'</b></a>') xml FROM str_csv
    )
    SELECT
        code, extractValue(value(t),'b') str_type
      FROM
        str_xml s,
        TABLE(XMLSequence(s.xml.extract('a/b'))) t
      WHERE extractValue(value(t),'b') is not null
    ;
    Ответ написан
    Комментировать
  • Как бэкапить БД Oracle?

    erge
    @erge
    Примус починяю
    В пределах ОС одного семейства (типа) просто "холодный" бекап - копирование файлов БД.
    с созданием соответствующего init файла и возможно пересозданием control файлов (если пути до базы различаются), так же настроить listener для прослушки соединений на БД, при этом сами СУБД должны быть полностью идентичны (одна и та же версия, разрядность и т.п.)

    PS: возможно не самый быстрый способ, но самый простой.

    PPS: если переносить между разными версиями СУБД и ОС, то имхо , только exp/imp
    можно еще по линкам данные перекачивать или велосипедные файловые репликации (но это между рабочими БД со структурой данных)...
    Ответ написан
    Комментировать
  • Как найти скрипт часов на этом сайте?

    erge
    @erge
    Примус починяю
    Открываете сайт например в Chrome, открываете "инструменты разработчика/инспектор кода" (Ctrl+Shift+I или F12), выбираете иконку "квадратик со стрелкой" (Select and element in the page to inspect it) или просто жмете Ctrl+Shift+C, тыкаете в блок с часами, в коде подсвечивается кусок:

    <td class="local_time0" data-tz="Europe/Saratov">Thu, 29 Apr 2021 09:50:04 +0400</td>


    соответственно запись производится в этот элемент, надо найти где и единственный разумный идентификатор этого элемента, не считая разных извращений, это class="local_time0"
    соответственно ищем строку local_time0 по коду и всем подгружаемым js-кам
    1. в лоб не получилось ничего не нашлось...
    2. ищем local_time и находим в файле js/ip.js (смотри вкладку Sources в инспекторе) функцию в которой происходит обращение к этому элементу:

    function t() {
            try {
                if (!i)
                    return !0;
                for (var t, e = new Date, a = ".local_time", n = [], r = [], o = 0; o < 2; o++)
                    n[o] && r[o] || (n[o] = $(a + o).data("tz"),
                    r[o] = $(a + o).text().substr(25)),
                    t = Intl.DateTimeFormat("en-GB", {
                        weekday: "short",
                        day: "2-digit",
                        month: "short",
                        year: "numeric",
                        hour: "numeric",
                        minute: "numeric",
                        second: "numeric",
                        timeZone: n[o]
                    }).format(e),
                    $(a + o).text(t.slice(0, 16) + t.slice(17) + r[o]);
                return !0
            } catch (t) {
                return !1
            }
        }
        t() && window.setInterval(t, 1e3)

    здесь же видно как получается local_time0
    a = ".local_time"
    o = 0

    и далее обращение к элементу посредством jquery
    $(a + o).text()

    как-то так...
    Ответ написан
    Комментировать
  • Как найти различающиеся по хэшу файлы в двух директориях с вложенными директориями?

    erge
    @erge
    Примус починяю
    под Windows : Total Commander, Unreal Commander, Double Commander
    под Linux: Double Commander
    функция - Команды - Синхронизировать каталоги (как-то так)
    mc и far вроде так же умеют сравнивать каталоги.

    скрипт лучше всего наверно написать на python (есть на любой ОС, хотя на любителя), взять за пример выше на VBS (честно не вчитывался) либо по своему написать, имхо - заносить хеши файлов в массив, затем сравнивать (ну как-то так)
    на bash предполагаю будет жутким извращением, хотя думаю что возможно.
    PS: в bash все равно не обойтись чистым bash, потребуется как минимум одна внешняя команда md5sum , которой в Windows скорее всего не будет и надо будет искать ее порт под Windows или аналог. Так же есть diff , который можно было бы использовать, но это опять же не встроенная в bash команда.

    так же
    GTBACKUP

    по rSync:
    поиск вообще пробовали? rsync windows
    cwRsync
    https://habr.com/ru/sandbox/48269/

    https://rsync.samba.org/

    либо даже Cygwin со всеми соответствующими плюшками.
    хотя, в Windows 10 есть целая подсистема Linux - WSL
    Ответ написан
    Комментировать
  • Как экспортировать базу JSON в MYSQL?

    erge
    @erge
    Примус починяю
    1. не экспорт, а импорт
    2. гуглите (яндексите) import json to mysql (есть море информации)
    3. если импортировать записи как в примере в простую таблицу в новую БД, то проще и быстрее как уже говорили выше - загружать напрямую в базу из CSV файла, а json конвертнуть в CSV при помощи sed например (одной строчкой)
    Ответ написан
    Комментировать
  • Существует ли Viber клиент API?

    erge
    @erge
    Примус починяю
    Может попробовать живой клиент Viber и AutoIt (на Windows) или его аналоги на Linux
    Ответ написан
    Комментировать
  • Как переименовать файлы по регулярному выражению?

    erge
    @erge
    Примус починяю
    Если прям на Windows Batch Scripting:
    CMD/BAT — Пакетное переименование файлов(.jpg) в разных папках (BAT)?
    https://stackoverflow.com/questions/21162119/regul...

    Если не принципиально, то использовать PowerShell:
    www.outsidethebox.ms/17857

    Либо поставить bash и как-то так:
    https://stackoverflow.com/questions/11809666/renam...
    в чистом bash, как-то так:
    find . -type f -name "Friends*" -execdir bash -c 'mv "$1" "${1/\w+\s*-\s*(\d)x(\d+).*$/S0\1E\2.srt}"' _ {} \;

    PS: пример выдернут из ссылки выше, не применительно к вашему случаю.
    Ответ написан
    Комментировать
  • Как сделать выборку постов из разных категорий в нужном количестве?

    erge
    @erge
    Примус починяю
    select name, test from (
      select name, test from (select name, test from post where category_id=2 limit 0,4) t2
      union
      select name, test from (select name, test from post where category_id=3 limit 0,5) t3
      union
      select name, test from (select name, test from post where category_id=1 limit 0,18) t1
    ) t
    limit 0,18


    см. пример на dbfiddle.uk
    Ответ написан
    Комментировать
  • В какой бесплатной програме можно создать резюме в формате PDF?

    erge
    @erge
    Примус починяю
    Такое резюме можно легко сделать в обычном MS Office или его бесплатном аналоге LibreOffice и экспортировать в PDF формат.
    Ответ написан
    Комментировать
  • Можно ли как-то обработать результат функции = #ЗНАЧ!?

    erge
    @erge Автор вопроса
    Примус починяю
    Уже сделал через ЕСЛИОШИБКА:

    =ЕСЛИОШИБКА(ЕСЛИ(ДЕНЬ(A1)>0;0;1);1)

    т.е. если не дата возвращается 1, если дата то 0
    это для условного форматирования.

    PS: в LibreOffice нет например ЕДАТА и пр., но ЕСЛИОШИБКА есть.
    валидация содержимого в ячейке (Данные -> Проверка) в LibreOffice тоже есть, выходит сообщение - "недопустимое значение"
    но не знаю будет ли это работать в Excel если сохранить из LibreOffice , формулы в условном форматировании работают.

    UPDATE:
    В Excel 2003 нет функции ЕСЛИОШИБКА (файл открывается как поврежденный, условное форматирование "слетает"), но есть ЕОШИБКА и она есть и в LibreOffice и в более старших Excel
    формула для условного форматирования и подсветки ячеек с некорректной датой будет такой:

    =ЕСЛИ(ЕОШИБКА(ДЕНЬ(F2));1;0)

    для подсветки пустых ячеек, дат с неполным годом, некорректно введенных дат - так:

    =ИЛИ(ДЛИНБ(F2)<>10; ЕСЛИ(ЕОШИБКА(ДЕНЬ(F2));1;0) )
    Ответ написан
    Комментировать
  • Как из БД выбрать товар рандомно?

    erge
    @erge
    Примус починяю
    По мотивам New_Horizons

    SELECT p.* FROM product p
      JOIN ( SELECT rand() * (SELECT max(id) FROM product WHERE p.name LIKE 'Горо%') AS max_id ) AS m
      WHERE p.id >= m.max_id
        AND p.name LIKE 'Горо%'
    ORDER BY p.id ASC LIMIT 1;


    про p.name LIKE 'Горо%'

    1. в подзапросе выбирается максимальный ID для товаров с соответствующим названием, т.к. если не ограничивать то выберется в принципе максимальный ID, а он может быть больше максимального ID нужного товара и если он выпадет в рандоме, то не выберется ничего.
    2. при выборе по ID >= рандомного max_id, ограничиваем выборку по нужному товару условием.
    Ответ написан
    Комментировать