Имя: Пароль:
1C
1C 7.7
v7: Программное определение секций таблицы
0 MadDAD
 
23.05.18
09:53
Надо кому?

Есть решение с использованием DynWrapperX
1 MadDAD
 
23.05.18
09:53
Вернее не определение а получение списка
2 MadDAD
 
23.05.18
10:07
Перем  ScrptCtrl;

Процедура ПатчBlang()
//Пропатчим blang по методике Chessman'а для передачи объектов 1C в DynWrapper
    ТекстМодуля         = "    
        |Public Const PAGE_EXECUTE_READWRITE    = &h40
        |
        |Public    Wrap
        |Set Wrap = CreateObject(""DynamicWrapperX"")
        |Wrap.Register ""Kernel32"", ""LoadLibrary"" , ""i=s"", ""r=h""
        |Wrap.Register ""Kernel32"", ""GetProcAddress"" , ""i=hs"", ""r=u""
        |Wrap.Register ""Kernel32"", ""VirtualProtect"" , ""i=lllp"", ""r=l""
        |Wrap.Register ""Kernel32"", ""HeapAlloc"",    ""i=lll"",    ""r=l""
        |Wrap.Register ""Kernel32"", ""GetProcessHeap"", ""r=l""
        |Wrap.Register ""Kernel32"", ""HeapFree"", ""i=lll"",""r=l""
        |'....................................................................
        |
        |Class DWX_Blang
        |    Private ptr
        |    Private hHeap
        |    Private buf    
        |    
        |    Private Sub Class_Initialize
        |        handle = Wrap.LoadLibrary(""blang"")
        |        Addr   = Wrap.GetProcAddress(handle, ""?CallAsFunc@CStdOleBLContext@@UAEHHAAVCValue@@PAPAV2@@Z"")
        |        Offset = &h3A9
        |        ptr       = Addr + Offset
        |
        |        hHeap  = Wrap.GetProcessHeap()
        |        buf    = Wrap.HeapAlloc(hHeap, 0, 4)
        |
        |        Wrap_Blang()
        |    End Sub
        |
        |    Private Sub Class_Terminate
        |        Wrap.HeapFree hHeap, 0, buf
        |    End Sub    
        |
        |    Private Sub Wrap_Blang()
        |        If Wrap.NumGet(ptr, 0, ""t"") = &h458D Then
        |            Exit Sub
        |        End If
        |        Wrap.VirtualProtect ptr, &h21, PAGE_EXECUTE_READWRITE, buf
        |        
        |        Wrap.NumPut &h458D    , ptr, 0,     ""t""        'LEA EAX,DWORD PTR SS:[EBP-40]
        |        Wrap.NumPut &hC0    , ptr, 2,     ""b""        '
        |        Wrap.NumPut &h0E8B    , ptr, 3,     ""t""        'MOV ECX,DWORD PTR DS:[ESI]
        |        Wrap.NumPut &h498B    , ptr, 5,     ""t""        'MOV ECX,DWORD PTR DS:[ECX+48]
        |        Wrap.NumPut &h48    , ptr, 7,     ""b""        '
        |        Wrap.NumPut &h00C7    , ptr, 8,     ""t""        'MOV DWORD PTR DS:[EAX],3
        |        Wrap.NumPut &h3        , ptr, 10,     ""u""
        |        Wrap.NumPut &h4889    , ptr, 14,     ""t""        'MOV DWORD PTR DS:[EAX+8],ECX
        |        Wrap.NumPut &h08    , ptr, 16,     ""b""        '
        |        Wrap.NumPut &h458D    , ptr, 17,     ""t""        'LEA EAX,DWORD PTR SS:[EBP-2C]
        |        Wrap.NumPut &hD4    , ptr, 19,     ""b""        '
        |        Wrap.NumPut &h00C7    , ptr, 20,     ""t""        'MOV DWORD PTR DS:[EAX],3
        |        Wrap.NumPut &h3        , ptr, 22,     ""u""
        |        Wrap.NumPut &h4889    , ptr, 26,     ""t""        'MOV DWORD PTR DS:[EAX+8],ECX
        |        Wrap.NumPut &h08    , ptr, 28,     ""b""        '
        |        Wrap.NumPut &hE9    , ptr, 29,     ""b""        'JMP 21011F3F
        |        Wrap.NumPut &h03C4    , ptr, 30,     ""u""        '
        |
        |        '....................Убираем за собой....................
        |        Wrap.VirtualProtect ptr, &h21, Wrap.NumGet(buf), buf
        |    End Sub
        |End Class
        |
        |Set Blang = New DWX_Blang
        |";
    ScrptCtrl              = СоздатьОбъект("MSScriptControl.ScriptControl");
    ScrptCtrl.Language     = "vbscript";
    ScrptCtrl.TimeOut    = -1;
    ScrptCtrl.AddCode(ТекстМодуля);            
        
КонецПроцедуры

//--------------------------------------------------------------------------------------------------------------------------------
Функция ПрочитатьСекцию(Указатель, НомерСекции, Таб)
    СекцияУказатель = DWX.NumGet(Указатель, 4) + НомерСекции * 20;
    Секция = СоздатьОбъект("СписокЗначений");
    Секция.Установить("Имя", DWX.StrGet(DWX.NumGet(СекцияУказатель,16),"s"));
    Секция.Установить("Начало",DWX.NumGet(СекцияУказатель, 4) +1);
    Секция.Установить("Конец", DWX.NumGet(СекцияУказатель, 8)+1);
    Секция.Установить("Уровень",DWX.NumGet(СекцияУказатель, 12));
    Возврат Секция;
КонецФункции

//--------------------------------------------------------------------------------------------------------------------------------
Процедура ПолучитьСекции(Таб)
    ПатчBlang();
    
    Лист = DWX.numGet(DWX.ObjPtr(Таб), 56); // [0x38h] CSheet*
    ВертикальныеСекцииУказатель = Лист + 480; // [0x1E0h] &CSheet->VLayout
    ГоризонтальныеСекцииУказатель= Лист + 460; // [0x1CCh] &CSheet->HLayout
    
    ГоризонтальныхыхСекций = DWX.NumGet(ГоризонтальныеСекцииУказатель, 8, "u"); //  &CSheet->HLayout->Num
    ВертикальныхСекций = DWX.NumGet(ВертикальныеСекцииУказатель, 8, "u"); // &CSheet->VLayout->Num
    
    Для Счетчик = 0 По ГоризонтальныхыхСекций - 1 Цикл
        Секция = ПрочитатьСекцию(ГоризонтальныеСекцииУказатель, Счетчик, Таб);
        ГоризонтальныеСекции.ДобавитьЗначение(Секция, Секция.Получить("Имя"));
    КонецЦикла;

    Для Счетчик = 0 По ВертикальныхСекций - 1 Цикл
        Секция = ПрочитатьСекцию(ВертикальныеСекцииУказатель, Счетчик, Таб);
        ВертикальныеСекции.ДобавитьЗначение(Секция, Секция.Получить("Имя"));
    КонецЦикла;
КонецПроцедуры
3 trdm
 
23.05.18
10:18
Ваше кунфу - божественно!
4 Ёпрст
 
23.05.18
12:18
(0) а.. применение то какое ? К чему это ?
5 MadDAD
 
23.05.18
13:09
(4) На самом деле это кусок класса-наследника таблицы. Возникла задача выяснить поместится ли секция на страницу. При выборе исходной таблицы получаю все секции и рассчитываю их высоты в твипах. Можно было бы не париться получением секций, но так уж получилось, что я раньше немного ковырял моксели и знал где что брать.

В качестве применения можно например в универсальной обработки печати документов выяснить есть ли в таблице секция "Подписи" к примеру или "Логотип" и если есть - вывести. А если нет - не выводить.
6 Злопчинский
 
23.05.18
18:40
(5) > "Возникла задача выяснить поместится ли секция на страницу"
- ну выведи секцию в черновик - если после вывода стало таб.КоличествоСтраниц() больше - значит не поместилась...
7 Злопчинский
 
23.05.18
18:42
ты лучше сюда посмотри https://www.forum.mista.ru/topic.php?id=818192&all=1 - 98 топик, второй врпрос
8 MadDAD
 
24.05.18
10:42
(6) Некрасиво :) для каждой таблицы держать еще и черновик, а так посчитал высоту таблицы в твипах с учетом масштабирования, посчитал высоту секции, посчитал количество листов и остаток на текущем листе и оценил.

Ну и штатный КоличествоСтраниц() - тормозной метод.