1

Тема: Задача WINAPI створення аналогу Exel

Я недавно почав працювати на фрілансі, місяць тому. Мені прийшли 2 замовлення, і обидва я провалив. І обидва цих замовлення пов'язані зі створенням забезпечення для ведення бухгалтерського обліку. Я дуже довго (4 дні) шукав, як зробити ці програми, але все ж не знайшов і відмовився від замовлень. Точніше, я не хотів покривати збитки замовникам.
Задача була приблизно такою:
На ОС Android/Windows створити програму бухгалтерського обліку на основі БД SQLite,
Меню:
Диски
Ланцюги
Лопати
...
Ну і кожен пункт має виводити на таке вікно, в якому є таблиця схожа на exel, і там мають бути стовпці
Товар    ПІП     Дата .... Кнопки
Диск  Іванов Іван 03.08.2019 перенести редагувати видалити
ну і от натискання на кнопку перенести має переносити запис з однієї таблиці SQLite в іншу і от така задача. Ну ви сподіваюсь зрозуміли
Ну я клієнтам сказав, звичайно, що це ізі. Що це звичайна БД і я без проблем справлюся з завданням.
У мене почалися проблеми вже на EditText, тобто кожна ячейка це має бути EditText (в андроїді в в віндовсі він зветься однаково).  Ну, припустимо я створюю масив із дескрипторів на таблицю мегабайтів 3, скільки це пам'яті буде? На андроїді - ще гірше. Пристрої мають замало ресурсів, а JVM множить ресурси програми на 6.
Потім - в кожному рядку цієї таблиці по бажанню замовника мають бути кнопки.
А це треба на кожну кнопку робити switch (case) ну і припустимо в таблиці 5000 рядків і треба проаналізувати 3 кнопки * 5000  = 15000 кнопок, ідентифікатори звичайно числові ну тобто без #define.
Потім там ще мають бути чекбокси для можливості одночасного перенесення чи видалення.
Загальний алгоритм такий:
1. відкриваємо базу
2. визначаємо кількість записів одного із стовпців
3. створюємо масив дескрипторів, який дорівнює (операція 2)*(3кнопки+1чекбокс+кількість стовпців_відома_для_кожного_вікнаокремо)
4. створюємо потік + прогресбар і заповнюємо наш масив з БД і кнопками
5. програма завершується невдало хоч на віндовс хоч на андроїд, після перевершення ліміту ресурсів, а на андроїді взагалі одразу після запуску
Код тут писати дуже  довго, вибачайте.
як вирішити цю проблему?

2 Востаннє редагувалося Torbins (04.08.2019 12:30:27)

Re: Задача WINAPI створення аналогу Exel

Ви знаєте які ліміти у справжнього Екселя? На нормальному залізі, він впорається з таблицею на 1 048 576 рядків та 16 384 стовпців, тобто здатен працювати з таблицею на 17 179 869 184 ячейок. І ви дійсно думаєте, що він створює для цього одразу сімнадцять мільярдів едітів?

Подякували: leofun011

3

Re: Задача WINAPI створення аналогу Exel

Ні, не думаю. Оце ж я і хотів взнати, як. Говорять, треба як Total Commander (Lister) підвантажувати тільки ті рядки які знаходяться на тій позиції, яку переглядає користувач. Та от не знаю, як це зробити бо не знаю, як взнати чи прокрутив користувач прокрутку. Тут алгоритм буде трохи інший. Але все одно проблемний.
1. Визначаємо розмір вікна (x, y)
2. Визначаємо розмір шрифту (x, y)
3. Визначаємо відступ (x, y)
4. Додаємо шрифт_х+(відступ_х*2), шрифт_у+(відступ_у*2)
5. Ділимо те що вийшло вікно_x/вийшло_х, вікно_y/вийшло_y
6. Множимо те що вийшло 5 (x*y)
7. Створюємо масив з дескрипторів (x*y), виділяємо пам'ять. заповнюємо з БД
8. Створюємо потік, який слідкує чи прокрутилась сторінка у вічному циклі
9. Якщо сторінка прокрутилась вниз, перезавантажуємо таблицю зі зміщенням + 1 елем.
10. Якщо сторінка прокрутилась вверх, перезавантажуємо таблицю зі зміщенням -1 елем.

//...
int GetMyWindowResolution[2](HWND hWnd)
{
RECT resolution;
int res[2];
resolution=GetWindowRect(hWnd, resolution);
res[0]=resolution.right - resolution.left;
res[1]=resolution.bottom - resolution.top;
return res;
}
int GetSettings[2]()
{
int font[2];
hFile = CreateFile("font.ini", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
    if(hFile != INVALID_HANDLE_VALUE) {
        DWORD dwFileSize;
        dwFileSize = GetFileSize(hFile, NULL);
        if(dwFileSize != 0xFFFFFFFF) {
            LPSTR pszFileText;
            pszFileText = (LPSTR)GlobalAlloc(GPTR, dwFileSize + 1);
            if(pszFileText != NULL) {
                DWORD dwRead;
                if(ReadFile(hFile, pszFileText, dwFileSize, &dwRead, NULL)) {
                    pszFileText[dwFileSize] = 0;
                    LPSTR padding_buff=new char[dwFileSize];
                                        LPSTR font_buff=new char[dwFileSize];
                                        int i=0;
                                        while (pszFileText[i]!='\n') {
                                        font_buff[i]=pszFileText[i];
                                        i++;
                                        }
                                        i++; //оминаємо \n
                                        int j=0;
                                        while (pszFileText[i]!=dwFileSize) {
                                        padding_buff[j]=pszFileText[i];
                                        i++;
                                        j++;
                                        }
                                        font[0]=atoi(font_buff);//1 результат
                                        font[1]=atoi(padding_buff);//2 результат 
                }
                GlobalFree(pszFileText);
            }
        }
        CloseHandle(hFile);
return font;
}
int GenerateParamTable(HWND hWnd)
{
int wndres[2]=GetMyWindowResolution(hWnd);
int font[2]=GetSettings();
int padding_x=font[0]*2;//розмір відступу вліво-вправо вверх-вниз однаковий
int padding_y=font[1]*2;//однаковий для прикладу щоб не писати багато коду
int result_x=padding_x+wndres[0];
int result_y=padding_y+wndres[1];
return result_x*result_y;
}
int CreateTable()
{
//...
HWND *wnd=new HWND[GenerateTableParam()];
//...
}
//...

поки що так але все одно десь є вильоти (програма невдало завершилась з кодом ....)
Як визначити чи прокрутив користувач сторінку, як я сказав вище, я не знаю. А тому для цієї цілі є спеціальні кнопки вверх і вниз, після натискання яких перезавантажуються таблиця зі зміщенням 1 рядку БД)
Код всією програми отакий і вигляд його мало чим нагадує щось нормальне.
Як нормально завантажити всі установки (їх більше 100?
Чи треба створювати таку кількість дескрипторів і т.д.?

4

Re: Задача WINAPI створення аналогу Exel

man написав:

Ні, не думаю. Оце ж я і хотів взнати, як. Говорять, треба як Total Commander (Lister) підвантажувати тільки ті рядки які знаходяться на тій позиції, яку переглядає користувач.

Ви не безнадійні, це єдиний позитив вашого посту.

man написав:

Та от не знаю, як це зробити бо не знаю, як взнати чи прокрутив користувач прокрутку.
...
8. Створюємо потік, який слідкує чи прокрутилась сторінка у вічному циклі
...
поки що так але все одно десь є вильоти (програма невдало завершилась з кодом ....)
Як визначити чи прокрутив користувач сторінку, як я сказав вище, я не знаю. А тому для цієї цілі є спеціальні кнопки вверх і вниз, після натискання яких перезавантажуються таблиця зі зміщенням 1 рядку БД)

*FACEPALM*  Якщо потік робили без синхронізації, то немає нічого дивного, що програма вилітає. Цей потік тут взагалі лишній, позицію скролів легко відслідковувати ловлячи WM_VSCROLL.

man написав:

7. Створюємо масив з дескрипторів (x*y), виділяємо пам'ять. заповнюємо з БД
...
Як нормально завантажити всі установки (їх більше 100?
Чи треба створювати таку кількість дескрипторів і т.д.?

Скажіть мені у скільки едітів одночасно користувач може вводити текст?

P.S. Вам однозначно треба почитати якусь книжку по WinAPI, перш ніж братися його використовувати.

Подякували: leofun011