Форум » [x]Harbour » Снова EXCEL (продолжение) » Ответить

Снова EXCEL (продолжение)

Dima: Ранее с Excel из Harbour ни когда не работал. Поставили тут задачу. У некоторых поставщиков есть определенные формы заказов. Набраны они в Excel. Сейчас народ руками заполняет эти формы и шлет по электронке поставщикам. Задача сводится к тому что бы в этих формах находить нужные коды товара и в нужной ячейке проставлять заказ. Может ткнет кто носом с чего начать что бы не напороться на грабли. Спасибо Сами формы тут http://zalil.ru/33279066

Ответов - 100, стр: 1 2 3 4 5 All

Sergy: Dima пишет: Что касаемо картинки ....проделывал уже такой эксперимент , результат выше описал. Excel 2000 и 2010 при формате ДД.ММ.ГГ показывает все четко, год двумя цифрами. А вот если задать DD.MM.YY - любую дату преобразует в целое число (видно в строке формул вверху), а внутри ячейки пишет (дословно) "DD.MM.YY"

Oskar_AAA: Добрый день, коллеги. Программа на xHarbour, выгружаю файлы MS Excel, затем собираем в сводный отчет данные из выгруженных файлов MS Excel. Слетают настройки цветов и форматов в сводном отчете... Пробовал на разных версиях MS Excel, закономерности пока не нашел. Но на 1 ПК всегда выгружается без сбоев.Операционные системы на всех ПК - Win7, офис возможно разный... Что может быть в тонкостях настройки MS Excel? Всех со "Старым" Новым Годом!!!

Sadstar2016: Help me pls. Длительное время работает такая схема формирования отчета в Excel 1.Грузится xls-файл - образец с отформатированной шапкой (соответственно - нужные ширины столбцов) Чтобы не портить образец ( юзера всегда умудрятся его перезаписать) 2.Копируется лист 3.Создается новая книга. 4.Вставка в лист новой книги. 5.Добавление строк отчета в новую книгу oExcel:Workbooks:Open(cFile) oBook:=oExcel:ActiveWorkbook() oBook:Worksheets(1):Cells:Copy() oBookN:=oExcel:WorkBooks:Add() //новая пустая книга oSheet:=oBookN:Worksheets(1) oSheet:Paste() Вдруг с некоторых пор на одном рабочем месте перестали копироваться ширины столбцов. Пытался найти отличия в настройках Excel-я влияющие на режим копирования - не нашел. Второй вариант - принудительное копирование ширин столбцов. В макросе это выглядит так Cells.Select Selection.Copy Workbooks.Add ActiveSheet.Paste //вставка ширин столбцов Selection.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, SkipBlanks:=False, Transpose:=False Как последнюю строку макроса переписать в терминах Харбора?

Петр: Пробуйте так (не проверял) #define xlPasteColumnWidths 8 #define xlPasteSpecialOperationNone -4142 Paste := oExcel:ActiveSheet():PasteSpecial(xlPasteColumnWidths, xlPasteSpecialOperationNone, False, False)

Sadstar2016: Error 1559948/3 DISP_E_MEMBERNOTFOUND: PASTESPECIAL похоже - не находит метод PASTESPECIAL P.S. без ошибок прошло oSheet:Cells:PasteSpecial(xlPasteColumnWidths, xlPasteSpecialOperationNone, .f., .F.)

Петр: Sadstar2016 пишет: без ошибок прошло oSheet:Cells:PasteSpecial(xlPasteColumnWidths, xlPasteSpecialOperationNone, .f., .F.) Ну да, поскольку PasteSpecial в Excel метод обьекта Range, Cells: там нужен oExcel:ActiveSheet():Cells:PasteSpecial Петр пишет: Пробуйте так (не проверял) Но вы не об этом и спрашивали Как я понял, суть вопроса - как преобразовать вызов метода, а не к чему этот метод применить

MIKHAIL: Sadstar2016 пишет: 1.Грузится xls-файл - образец с отформатированной шапкой (соответственно - нужные ширины столбцов) Чтобы не портить образец ( юзера всегда умудрятся его перезаписать) Может проще скопировать файл шаблона и работать с ним?

Sadstar2016: IMHO - пусть юзер сам решает - где и под каким именем хранить файл - если его вообще нужно хранить

fil: На листе Excel создаю кнопку oExc:Sheets(1):Buttons:Add(120, 20+30*(cnt-1), 350, 22) и указываю макрос, который должен выполниться при клике на этой кнопке oExc:Sheets(1):Buttons(cnt):OnAction:="Макрос1" А как можно сделать вызов этого макроса с параметром ?

fil: Параметр, видимо, передать нельзя. Но можно использовать свойство кнопки Parameter, а в макросе поймать эту кнопку через Caller

TimTim: Нужно из xHarboura при заполнении Excel-файла задать формат поля "Денежный". Офис 2013. При вводе туда числа должен появляться символ ₽ ( Unicode 20BD ). Если сделать в самом Excel формат ячейки "Денежный" то все нормально. Кстати, этот новый символ рубля сидит на Правом Alt + 8. Попробовал вставить формат, который выдает макрос: Selection.NumberFormat = "#,##0.00 $" Переделал под xHarbour: NumberFormat := '# ##0,00 $ ' Добавляется только символ доллара в конце, что навело на мысль попробовать формат '# ##0,00 p.' с английской p, или HB_OemToAnsi( '# ##0,00 руб.' ). Все получилось, буковки появляются, числа можно складывать и т.д. Но все-таки, как быть с символом ₽?

Haz: TimTim пишет: Попробовал вставить формат, который выдает макрос: Selection.NumberFormat = "#,##0.00 $" макрос выдает другой формат при выборе значка рубля Selection.NumberFormat = "#,##0.00 [$?-419]" но OLE это тоже не понимает

Andrey: Всем привет ! Использую Ms Офис 2003 SP3. Периодически появляется дурацкая табличка: Как от неё избавиться ? Есть ли какой то флаг для этого сообщения ?

Dima: Andrey Погугли

Andrey: Dima пишет: Погугли Ничего для себя не нашёл. Методом проб и ошибок выяснил - неправильную работу в МиниГуи функции oBrw:Excel2(...) при вот вот таком формате вывода в Эксель: oBrw:aColumns[nJ]:cDataType := 'N' oBrw:aColumns[nJ]:cPicture := '99:99' Как исправить ?

Andrey: Обрезает нули в Екселе для текстового формата. Вывожу текстовые данные поля бд в ячейку - типа "0000345", указываю в ячейке формат: oSheet:Cells( nLine, nI ):SET( "NumberFormat", '@' ) // текстовая ячейка Как избавиться от обрезания ?

Dima: Поставь формат что то типа 0000000000 Где кол-во нулей равно длине строки в твоем случае 0000000

Andrey: Dima пишет: Поставь формат что то типа 0000000000 Спасибо ! Но тогда разрушается универсальность функции перекодировки Dbf->Xls. Текстовые данные могут быть разными. Я у себя делаю так: ............ cPole := aField[ nI , 1 ] xValue := FIELDGET( FIELDNUM( cPole ) ) // значени полей DBF nDecPole := FieldDec( FIELDNUM( cPole ) ) // для формата числа oSheet:Cells( nLine, nI ):Value := xValue IF FIELDTYPE( cPole ) == "C" oSheet:Cells( nLine, nI ):SET( "NumberFormat", '@' ) // текстовая ячейка ELSEIF FIELDTYPE( cPole ) == "N" IF nDecPole == 0 // значит целое число oSheet:Cells( nLine, nI ):SET( 'NumberFormat', '## ### ###0' ) // числовая ячейка ELSE oSheet:Cells( nLine, nI ):SET( 'NumberFormat', '## ### ###0,00' ) // числовая ячейка ENDIF ELSEIF FIELDTYPE( cPole ) == "D" oSheet:Cells( nLine, nI ):SET( "NumberFormat", 'm/d/yy' ) // дата ячейка ELSE oSheet:Cells( nLine, nI ):SET( "NumberFormat", '@' ) // текстовая ячейка ENDIF .....

Dima: Andrey Тогда читай https://support.office.com/ru-ru/article/%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0-%D0%BD%D0%B0%D1%87%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85-%D0%BD%D1%83%D0%BB%D0%B5%D0%B9-%D0%B8-%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%86%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D1%8B%D1%85-%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2-57f15d52-5c75-4a67-ad35-394ae944d347

Dima: Andrey пишет: IF FIELDTYPE( cPole ) == "C" oSheet:Cells( nLine, nI ):SET( "NumberFormat", '@' ) // текстовая ячейка а вот тут нужна доп проверка а не цифры ли там одни живут и если так то NumberFormat будет другим. PS По ходу не нашел (может искал плохо или еще что ) такой функции "а не цифры ли там одни живут" , так что придется лепить свою.

Haz: Andrey пишет: Я у себя делаю так: Попробуй сначала задать формат а потом присвоить значение в ячейку

Dima: Haz пишет: Попробуй сначала задать формат а потом присвоить значение в ячейку Работает однако.

Dima: Может и была тема , не нашел. Нужно через Ole , иметь возможность только смотреть и печатать документ Excel. PS Сам документ формируется с установкой пароля на изменение. С этим нет проблем.

Pasha: Можно вызвать метод: Sheet:PrintPreview()

Dima: Pasha пишет: Можно вызвать метод: Sheet:PrintPreview() Да не плохой вариант , но если закрыть Preview то снова окажусь в Excel а там делай что хош.

Pasha: А если так: Excel:Visible := .t. Sheet:PrintPreview() Excel:Visible := .f.

Dima: Pasha пишет: Excel:Visible := .f. Заработало Спасибо

Pasha: В office 2013 и office 2010 с последними обновлениями появилась новая неприятная хворь: При открытии документа методом Excel:Workbooks:Open происходит или ошибка открытия, или зависание при выполнении метода. Хворь проявляется у Excel, и иногда у Word. У меня шаблоны документов хранятся на letodb сервере. Перед открытием я их копирую в папку temp из getenv('temp'). Причем одни шаблоны могут открываться нормально (это Word), а другие - нет. С Excel ситуация такая: после открытия документа он заполняется, и остается на экране для дальнейших действий с ним пользователя. Пользователь что-то с ним делает (печатает), и закрывает Excel. Оказывается, что процесс Excel остается висеть в памяти, а шаблон в папке Temp залочен им, и последующее открытие этого шаблона невозможно. Причем, такая ситуация проявляется нестабильно: два раза Excel может закрыться нормально, а на третий - затык. Если не переписывать файлы в папку temp, а хранить их в другой папке, то хворь не проявляется совсем. Иногда хворь проходит, если пошаманить с таким бубном: "Откройте вкладку Файл, чтобы переключиться в представление Microsoft Office Backstage. В меню Справка выберите пункт Параметры; отобразится диалоговое окно Параметры. Щелкните элемент Центр управления безопасностью и нажмите кнопку Параметры центра управления безопасностью. В центре управления безопасностью щелкните пункт Параметры блокировки файлов. Установите флажок Открывать выбранные типы файлов в режиме защищенного просмотра и разрешить редактирование." Но такие танцы с бубном помогают не во всех случаях. Пока я выкручиваюсь заменой магической заколдованной папки temp на другую папку, а там кто знает, как эта хворь будет вести себя дальше. Если занемог Office 2010 и обновлениями, то помогает его снос и установка версии с диска и отключением обновлений. У Office 2013 хворь врожденная.

Dima: Pasha пишет: Перед открытием я их копирую в папку temp из getenv('temp') Тоже так делаю , но в папке Temp создаю свою папку и уже копирую в нее , проблем не было ни разу. PS Office 2003

Pasha: проблем не было ни разу. Значит, жди сюрпризов с новыми офисами.

Dima: Pasha Ключевая фраза "в папке Temp создаю свою папку и уже копирую в нее" , может и у тебя сработает кто знает.

Sadstar2016: для справки Задача - Переместить лист в первую позицию Исходные данные ----------------------------------- 1. Макрос Sheets("Лист3").Select Sheets("Лист3").Move Before:=Sheets(1) ----------------------------------- 2.Функция VBA Moves the sheet to another location in the workbook. expression.Move(Before, After) expression Required. An expression that returns an object in the Applies To list. Before Optional Variant. The sheet before which the moved sheet will be placed. You cannot specify Before if you specify After. After Optional Variant. The sheet after which the moved sheet will be placed. You cannot specify After if you specify Before. Remarks If you don't specify either Before or After, Microsoft Excel creates a new workbook that contains the moved sheet. Example This example moves Sheet1 after Sheet3 in the active workbook. Worksheets("Sheet1").Move after:=Worksheets("Sheet3") ----------------------------------- 3.Работающий вариант oBook:Sheets("Итого"):Move( oBook:Sheets(1) ) //поставить перед листом N1

Oskar_AAA: Добрый день, как вернуть активным окно программы, после запуска Excel (формирование сводного отчета. 60 и более листов) из отдельных Excel файлов...? начало формирования сводного отчета oExcel_S:=ToleAuto():New("Excel.Application") oExcel_S:Workbooks:Open(Day_Excel) oExcel_S:Set("DisplayAlerts",.F.) oExcel_S:Visible :=.T. oBook_S :=oExcel_S:ActiveWorkBook oAs_S :=oExcel_S:ActiveSheet() oSheet_S:=oBook_S :Sheets(1):Select() oSheet_S:=oBook_S :Sheets(1) oAs_S :Cells(1,15):Select() .... формирование листов из отдельных Excel файлов // переход к сводному отчету Hb_GtInfo(HB_GTI_CLIPBOARDDATA, "") oSheet_S:=oBook_S :Sheets(1):Select() oBook_S :=oExcel_S :ActiveWorkBook oAs_S :=oExcel_S :ActiveSheet() oSheet_S:=oBook_S :Sheets(1) oAs_S :Cells(1,5):Select() oSheet_S:Cells(1,5):Value=Dtoc(Date())+', '+Substr(Time(),1,5) oAs_S :Cells(1,7):Select() oSheet_S:Cells(1,7):Value=SecToTim(Seconds()-Start_Beg) oAs_S :Cells(1,1):Select() oBook_S :SaveAs(Upper(Day_Excel)) oExcel_S:Quit() oAs_S :=Nil oRange_S:=Nil oBook_S :=Nil oExcel_S:=Nil использовать oExcel_S:Visible :=.F. не вариант, надо что бы процесс формирования сводного Excel отчета был виден в фоновом окне, а окно программы стало активным... PS:xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6476)

Andrey: Oskar_AAA пишет: как вернуть активным окно программы, после запуска Excel Надо получить хендл своей программы и переключиться на неё. Используй несколько функций из МиниГуи: GETWINDOW() потом BRINGWINDOWTOTOP() #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> #include <shlobj.h> #include "hbapi.h" #include "hbapiitm.h" #include "hbvm.h" // ---------------- взято из MiniGui ----------------------------- HB_FUNC( FINDWINDOWEX ) { hb_retnl( ( LONG ) FindWindowEx( ( HWND ) hb_parnl( 1 ), ( HWND ) hb_parnl( 2 ), ( LPCSTR ) hb_parc( 3 ), ( LPCSTR ) hb_parc( 4 ) ) ); } HB_FUNC( ISICONIC ) { hb_retl( IsIconic( (HWND) hb_parnl(1)) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } // --------------------------------------------- HB_FUNC( ISEXERUNNING ) // ( cExeNameCaseSensitive ) --> lResult { HANDLE hMutex = CreateMutex( NULL, TRUE, (LPTSTR) hb_parc(1) ); hb_retl( GetLastError() == ERROR_ALREADY_EXISTS ); ReleaseMutex( hMutex ); } HB_FUNC( GETFOREGROUNDWINDOW ) { hb_retnl( (LONG) GetForegroundWindow() ); } HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl(1) ); } HB_FUNC ( FINDWINDOW ) { hb_retnl( ( LONG ) FindWindow( 0, hb_parc( 1 ) ) ); } HB_FUNC( MINIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_MINIMIZE ); } HB_FUNC( MAXIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); ShowWindow( (HWND) hb_parnl(1), SW_MAXIMIZE ); } HB_FUNC( MAXIRESTORE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); } HB_FUNC( GETWINDOWTEXT ) { int iLen = SendMessage( (HWND) hb_parnl(1), WM_GETTEXTLENGTH, 0, 0 ) + 1; char *cText = ( char * ) hb_xgrab( iLen ); GetWindowText( (HWND) hb_parnl(1), (LPTSTR) cText, iLen ); hb_retc( cText ); hb_xfree( cText ); } HB_FUNC( GETWINDOW ) { hb_retnl( (LONG) GetWindow((HWND) hb_parnl(1), hb_parni(2)) ); } #pragma ENDDUMP Только вот как получить хендл своей программы в хХарборе пока не знаю...

Oskar_AAA: Тоже попробовал использовать HB_FUNC( MINIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_MINIMIZE ); } HB_FUNC( MAXIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); ShowWindow( (HWND) hb_parnl(1), SW_MAXIMIZE ); } HB_FUNC( MAXIRESTORE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); } тестирую...

Andrey: Вот ещё посмотри, для хХарбора раньше делал: ************************************************************************* * Copyright : (c) 2008, Verchenko Andrey. E-mail: 30195@mail.ru * : Все права сохраняются. * Date : 11/11/2008 * Avtor : Верченко Андрей * Rem : Получение списка ХЕНДЛов окон и ИМЕН окон запущенных в системе * : только на xHarbour'e * : Отдельное СПАСИБО модераторам: Петру и Григорию * : http://clipper.borda.ru/?1-1-0-00000159-000-0-1-1226399294 ************************************************************************** #include "common.ch" #include "inkey.ch" FUNCTION MAIN() LOCAL aStart := {}, nI, aMenu:={}, aItems:={}, nSelect, cTemp LOCAL nSEL, cMess, aOpt cMess := "Выберите действие с этим процессом..." aOpt := {"Свернуть","Развернуть","Спрятать","Показать","Убить"} STRFILE("","Process.lst", .F.) aStart := GetWindowList() // Считать ХЕНДЛ окна и ИМЯ окна FOR nI:= 1 TO LEN(aStart) AADD( aMenu, { aStart[nI,1], HB_ANSITOOEM(aStart[nI,2]) } ) cTemp := STR(aStart[nI,1])+", "+HB_ANSITOOEM(aStart[nI,2]) AADD( aItems, cTemp ) STRFILE( cTemp+CHR(13)+CHR(10),"Process.lst",.T.) NEXT CLEAR SCREEN @ 1,7 SAY "Хендл окна Название окна" COLOR("11/0") DO WHILE LastKey() <> K_ESC nSelect := Achoice( 2, 5, MaxRow()-2, 75, aItems, .T. ) IF nSelect <> 0 // ВЫБОР ДЕЙСТВИЯ nSEL := Alert(cMess,aOpt) DO CASE CASE nSEL == 1 MINIMIZE( aStart[nSelect,1] ) Alert("Окно было свернуто") CASE nSEL == 2 // Display selected file MAXIMIZE( aStart[nSelect,1] ) Alert("Окно было развернуто на весь экран") CASE nSEL == 3 HIDE( aStart[nSelect,1]) Alert("Окно сделано невидимым") CASE nSEL == 4 SSHOW( aStart[nSelect,1]) Alert("Окно стало видимым") CASE nSEL == 5 KKILL( aStart[nSelect,1]) Alert("Окну отправлена команда на закрытие") ENDCASE KEYBOARD Chr(255) // sets Lastkey() to 255 Inkey() ENDIF ENDDO RETURN NIL #define GW_HWNDFIRST 0 #define GW_HWNDLAST 1 #define GW_HWNDNEXT 2 #define GW_HWNDPREV 3 #define GW_OWNER 4 #define GW_CHILD 5 function GetWindowList() LOCAL aWindows := {}, cTitle := "" LOCAL hWnd := GetWindow( GetForegroundWindow(), GW_HWNDFIRST ) WHILE hWnd != 0 // Loop through all the windows if !empty(cTitle := GetWindowText( hWnd )) AADD( aWindows, {hWnd, upper(cTitle)} ) endif hWnd := GetWindow( hWnd, GW_HWNDNEXT ) // Get the next window ENDDO return aWindows #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> #include <shlobj.h> #define VM_CLOSE 16 HB_FUNC( ISEXERUNNING ) // ( cExeNameCaseSensitive ) --> lResult { HANDLE hMutex = CreateMutex( NULL, TRUE, (LPTSTR) hb_parc(1) ); hb_retl( GetLastError() == ERROR_ALREADY_EXISTS ); ReleaseMutex( hMutex ); } HB_FUNC( GETFOREGROUNDWINDOW ) { hb_retnl( (LONG) GetForegroundWindow() ); } HB_FUNC( MINIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_MINIMIZE ); } HB_FUNC( MAXIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); } HB_FUNC( HIDE ) { ShowWindow( (HWND) hb_parnl(1), SW_HIDE ); } HB_FUNC( SSHOW ) { ShowWindow( (HWND) hb_parnl(1), SW_SHOW ); } HB_FUNC( KKILL ) { SendMessage( (HWND) hb_parnl(1), VM_CLOSE,0,0); //DestroyWindow( (HWND) hb_parnl(1), VM_CLOSE); } HB_FUNC( GETWINDOWTEXT ) { int iLen = SendMessage( (HWND) hb_parnl(1), WM_GETTEXTLENGTH, 0, 0 ) + 1; char *cText = ( char * ) hb_xgrab( iLen ); GetWindowText( (HWND) hb_parnl(1), (LPTSTR) cText, iLen ); hb_retc( cText ); hb_xfree( cText ); } HB_FUNC( GETWINDOW ) { hb_retnl( (LONG) GetWindow((HWND) hb_parnl(1), hb_parni(2)) ); } #pragma ENDDUMP

Dima: Oskar_AAA Попробуй где то в самом начале своей программы после любого вывода на экран получить хендл своего окна с помощью GETFOREGROUNDWINDOW (взять можно в Минигуи) А после запуска Excel используй ShowWindow + BringWindowToTop (взять можно в Минигуи)

Oskar_AAA: Dima можно выслать из Минигуи GETFOREGROUNDWINDOW и ShowWindow + BringWindowToTop я не работал в Минигуи... Спасибо...

Dima: Oskar_AAA [pre2] #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } #pragma ENDDUMP [/pre2] [pre2] #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> #include "hbapiitm.h" HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( SHOWWINDOW ) { ShowWindow( ( HWND ) hb_parnl( 1 ), HB_ISNUM( 2 ) ? hb_parni( 2 ) : SW_SHOW ); } HB_FUNC( SETFOCUS ) { hb_retnl( ( LONG_PTR ) SetFocus( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } #pragma ENDDUMP [/pre2]

Oskar_AAA: Спасибо, начну тестировать...

Oskar_AAA: Dima вылетает по ошибке Warning W8065 Call to function 'HB_ISNUM' with no prototype in function HB_FUN_SHOWWINDOW вот фрагмент головного модуля... Procedure MAIN(Shifr) //INGAZ # Include 'Achoice.Ch' # Include 'Inkey.Ch' # Include 'Directry.Ch' # Include 'Setcurs.Ch' # Include 'Dbstruct.Ch' # Include 'Command.Ch' # Include 'Dbedit.Ch' # Include 'Excel.Ch' # Include 'Hbgtinfo.Ch' # Include 'Dbedit.Ch' Public Ctitle Ctitle:='INGAZ' C_Title=Ctitle+'.EXE' // SetConsoleTitle(cTitle) hWnd := FindWindow( cTitle ) DeleteCloseButton( hWnd ) #PRAGMA BEGINDUMP # include "Hbapi.h" # include "Windows.h" # include "Hbapiitm.h" HB_FUNC( SETCONSOLETITLE ) { hb_retl( SetConsoleTitle( hb_parc( 1 ) ) ) ; } HB_FUNC( FINDWINDOW ) { hb_retnl( (LONG)FindWindow( NULL, hb_parc( 1 ) ) ) ; } HB_FUNC( DELETECLOSEBUTTON ) { DeleteMenu(GetSystemMenu( (HWND)hb_parnl( 1 ), FALSE), SC_CLOSE, MF_BYCOMMAND ) ; DrawMenuBar( (HWND)hb_parnl( 1 ) ) ; } HB_FUNC_STATIC( SETFILEAPIS ) // OEM { SetFileApisToOEM(); } HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( SHOWWINDOW ) { ShowWindow( ( HWND ) hb_parnl( 1 ), HB_ISNUM( 2 ) ? hb_parni( 2 ) : SW_SHOW ); } HB_FUNC( SETFOCUS ) { hb_retnl( ( LONG_PTR ) SetFocus( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } #pragma ENDDUMP // REQUEST HB_CODEPAGE_RU866 REQUEST DBFCDX,DBFFPT HB_SetCodePage( "RU866" ) RDDSetDefault('DBFCDX') SetMode(25,80)

Dima: Oskar_AAA пишет: вылетает по ошибке Warning W8065 Call to function 'HB_ISNUM' Нужно смотреть какой аналог этой функции в Xharbour , я "сижу" на Harbour

Pasha: ISNUM( 2 ) регистр существенен.

Oskar_AAA: Коллеги, функция SETCONSOLETITLE (удаление возможности закрыть программу по "крестику") работает не зависимо от регистра.. в HbApi.h нашел #define ISNUM( n ) ( hb_param( n, HB_IT_NUMERIC ) != NULL )

Dima: Oskar_AAA пишет: Коллеги, функция SETCONSOLETITLE (удаление возможности закрыть программу по "крестику") работает не зависимо от регистра.. Не вижу связи крестика и функции что рисует заголовок у окна. Или я вопрос не понял ?

Oskar_AAA: Pasha пишет: ISNUM( 2 ) регистр существенен.

Oskar_AAA: Добрый вечер, с Вашей помощью вот что получилось: В головной программе, после вывода меню на экран Handl_Win=GetForeGroundWindow() ?Handl_Win 5178634 далее обработка БД и создание Xls файлов (43 шт) создание из макета сводного отчета Xls с 42 листами oExcel_S:=ToleAuto():New("Excel.Application") oExcel_S:Workbooks:Open(Day_Excel) oExcel_S:Set("DisplayAlerts",.F.) oExcel_S:Visible :=.T. // ¢¨§ã «¨§ æ¨ï ᢮¤-®£® ®âç¥â  oBook_S :=oExcel_S:ActiveWorkBook oAs_S :=oExcel_S:ActiveSheet() oSheet_S:=oBook_S :Sheets(1):Select() oSheet_S:=oBook_S :Sheets(1) oAs_S :Cells(1,15):Select() oSheet_S:Cells(1,15):Value=Cdata // ¤ â  ®âç¥â  oSheet_S:Cells(1,18):Value=Bom(Cdata) // ¤ â  - ç «  ¬¥áïæ  oAs_S :Cells(1,1):Select() // ShowWindow(Handl_Win) BringWindowToTop(Handl_Win) SetFocus(Handl_Win) ?Handl_Win 5178634 wait перехода (активации) к программе из Excel не происходит... что сделано не так???

Andrey: Oskar_AAA пишет: перехода (активации) к программе из Excel не происходит... что сделано не так??? Найди хендл окна Excel и потом переключись на него ! Хенд у окна Excel получить просто - смотреть пример ExcelOle.prg .... выложил готовые примеры у Григория на сайте - http://hmgextended.com/applications.html [pre2] // окно таблицы Excel на передний план hWnd := oExcel:hWnd ShowWindow( hWnd, 6 ) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 INKEYGUI(100) ShowWindow( hWnd, 3 ) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 BringWindowToTop( hWnd ) [/pre2]

Oskar_AAA: Andrey окно Excel и так является активным, мне надо его сделать видимым но не активным, т.е пусть будет на экране в фоновом режиме... или если Хенд Excel просто получить, надо сделать окно таблицы на второй план как? Спасибо. Посмотрю ссылки Григория

Dima: Oskar_AAA пишет: ShowWindow(Handl_Win) Тут имеет значение 2 параметр если не ошибаюсь. Андрей уже показал. У Вас его нет совсем.

Oskar_AAA: поставил из из его модуля hWnd := oExcel_S:hWnd ShowWindow( hWnd, 6 ) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 окно Excel стало маленьким, но осталось на переднем плане, как его сделать на ВТОРОМ плане?

fil: Поменять Z-последовательность окна можно через SetWindowPos, а проще ShowWindow другого-какого окна вот Excel и уйдет в фон. Можно свое окно посадить на передний план

Oskar_AAA: FIL Как свое окно СНОВА посадить на Передний план (вычислил Хедлы по своей программе и Excel). но : в головном модуле: Askar_Win=GetForeGroundWindow() hWnd := oExcel_S:hWnd *ShowWindow(hWnd,6) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 ShowWindow(hWnd,3) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 // ShowWindow(Askar_Win,3) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 BringWindowToTop(Askar_Win) на передний план сове окно не возвращается..

fil: SetWindowPos(hWnd, -1, 0,0,0,0,3)

Dima: Oskar_AAA А если так [pre2] if isiconic(Askar_Win) SetForeGroundWindow(Askar_Win) endif ShowWindow(Askar_Win, 9) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 BringWindowToTop(Askar_Win) [/pre2] Задача под каким терминалом собрана ? Под GTWVT у меня такая связка работает.

Oskar_AAA: Dima попробуем, рахмат... программа xHarbour - консольный 25 х 80,

Oskar_AAA: Dima где взять функцию Isconic()? if isiconic(Askar_Win) ///

Andrey: Oskar_AAA пишет: где взять функцию Isconic()? Смотри в этой ветке Пост N: 5282 HB_FUNC( ISICONIC )

Oskar_AAA: ok

Dima: Oskar_AAA Наваял простой пример на Harbour , терминал STD. Запускаем пример и после куда то переключаемся. Через 10 секунд , окно примера появляется , но окно фокус ввода не получает , даже если и указать Setfocus(Askar_Win). Но если собрать под терминалом GTWVT , добавив REQUEST HB_GT_WVT_DEFAULT то все работает , как я выше и писал. PS Может Паша или Пётр чего подскажут [pre2] ? "Test" Askar_Win:=GETFOREGROUNDWINDOW() Inkey(10) if isiconic(Askar_Win) SetForeGroundWindow(Askar_Win) endif ShowWindow(Askar_Win, 9) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 BringWindowToTop(Askar_Win) wait ************** #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> #include "hbapiitm.h" HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( ISICONIC ) { hb_retl( IsIconic( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SHOWWINDOW ) { ShowWindow( ( HWND ) hb_parnl( 1 ), HB_ISNUM( 2 ) ? hb_parni( 2 ) : SW_SHOW ); } HB_FUNC( SETFOCUS ) { hb_retnl( ( LONG_PTR ) SetFocus( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } #pragma ENDDUMP [/pre2]

Oskar_AAA: Dima программа xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6476). консольная (25 х 80) REQUEST HB_CODEPAGE_RU866 REQUEST DBFCDX,DBFFPT HB_SetCodePage( "RU866" ) RDDSetDefault('DBFCDX') SetMode(25,80) если REQUEST HB_GT_WVT REQUEST HB_GT_WVT_DEFAULT и подключаю GTWVT.lib при запуске программы выводится сообщение Unrecoverable error 10001 It's not a GUI programm переделывать под GUI - времени вообще нет... PS все функции Ваши & Andrey собрались и по ним ошибок при сборке программы нет. If Isiconic(Askar_Win) SetForeGroundWindow(Askar_Win) Endif ShowWindow(Askar_Win,9) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 BringWindowToTop(Askar_Win) set color to w/n ?hWnd,Askar_Win,Isiconic(Askar_Win) wait выдают числовые значения, Isiconic(Askar_Win)= .F.

Dima: Oskar_AAA К сожалению по Xharbour ни чего сказать не могу , давно слез с него на Harbour

Oskar_AAA: Коллеги, получилось в консольном xHarbour управлять окном и размером окна Excel с передачей фокуса на программу. Dima, Andrey и всем откликнувшемся - Рахмат # Include 'Achoice.Ch' # Include 'Command.Ch' # Include 'Dbedit.Ch' # Include 'Dbstruct.Ch' # Include 'Directry.Ch' # Include 'Excel.Ch' # Include 'Inkey.Ch' # Include 'Setcurs.Ch' # Include 'Hbgtinfo.Ch' // крестик на окне программы SetConsoleTitle(CTitle) hWnd:=FindWindow(CTitle) DeleteCloseButton(hWnd) // имена файлов в кириллице SetFileApis() // •Ґ-¤« ®Є®- Public Askar_Win1,Askar_Win2 Askar_Win1=GetForeGroundWindow() Askar_Win2=GetWindow() // REQUEST HB_CODEPAGE_RU866 REQUEST DBFCDX,DBFFPT HB_SetCodePage( "RU866" ) RDDSetDefault('DBFCDX') SetMode(25,80) обработка и так далее (создание временных Excel файлов....) создание сводного Excel отчета со многими листами из временных Excel файлов oExcel_S:=ToleAuto():New("Excel.Application") oExcel_S:Workbooks:Open(Day_Excel) oExcel_S:Set("DisplayAlerts",.F.) oExcel_S:Visible :=.T. // ўЁ§г «Ё§ жЁп бў®¤-®Ј® ®взҐв  oBook_S :=oExcel_S:ActiveWorkBook oAs_S :=oExcel_S:ActiveSheet() oSheet_S:=oBook_S :Sheets(1):Select() oSheet_S:=oBook_S :Sheets(1) oAs_S :Cells(1,15):Select() oSheet_S:Cells(1,15):Value=Cdata // ¤ в  ®взҐв  oSheet_S:Cells(1,18):Value=Bom(Cdata) // ¤ в  - з «  ¬Ґбпж  oAs_S :Cells(1,1):Select() // управление окнами hWnd := oExcel_S:hWnd ShowWindow(hWnd,3) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 If Askar_Win1>0 SetForeGroundWindow(Askar_Win1) Endif ShowWindow(Askar_Win1,9) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 BringWindowToTop(Askar_Win1) // вывод программы на ПЕРЕДНИЙ план сборка листов отчета #PRAGMA BEGINDUMP # include "Hbapi.h" # include "Windows.h" # include "Hbapiitm.h" # include "Shlobj.h" HB_FUNC( SETCONSOLETITLE ) { hb_retl( SetConsoleTitle( hb_parc( 1 ) ) ) ; } HB_FUNC( FINDWINDOW ) { hb_retnl( (LONG)FindWindow( NULL, hb_parc( 1 ) ) ) ; } HB_FUNC( DELETECLOSEBUTTON ) { DeleteMenu(GetSystemMenu( (HWND)hb_parnl( 1 ), FALSE), SC_CLOSE, MF_BYCOMMAND ) ; DrawMenuBar( (HWND)hb_parnl( 1 ) ) ; } HB_FUNC( SETFILEAPIS ) // OEM { SetFileApisToOEM(); } HB_FUNC( ISICONIC ) { hb_retl( IsIconic( (HWND) hb_parnl(1)) ); } // ®ЇаҐ¤Ґ«Ґ-ЁҐ  ЄвЁў-®Ј® ®Є-  HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( SHOWWINDOW ) { ShowWindow( ( HWND ) hb_parnl( 1 ), SW_SHOW ); } HB_FUNC( SETFOCUS ) { hb_retnl( ( LONG_PTR ) SetFocus( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( GETWINDOWTEXT ) { int iLen = SendMessage( (HWND) hb_parnl(1), WM_GETTEXTLENGTH, 0, 0 ) + 1; char *cText = ( char * ) hb_xgrab( iLen ); GetWindowText( (HWND) hb_parnl(1), (LPTSTR) cText, iLen ); hb_retc( cText ); hb_xfree( cText ); } HB_FUNC( GETWINDOW ) { hb_retnl( (LONG) GetWindow((HWND) hb_parnl(1), hb_parni(2)) ); } #PRAGMA ENDDUMP

Dima: Oskar_AAA пишет: и подключаю GTWVT.lib при запуске программы выводится сообщение Unrecoverable error 10001 It's not a GUI programm переделывать под GUI - времени вообще нет... GUI тут совсем не при чем.

Pasha: Здесь: https://support.microsoft.com/ru-ru/kb/124103 написано, как получить hWnd для консоли через вызов FindWindow так же есть оговорка: Полученный дескриптор HWND не обязательно подходит для всех операций дескриптор окна. Если немного модифицировать функции winapi, чтобы проанализировать возвращаемые значения: HB_FUNC( BRINGWINDOWTOTOP ) { hb_retnl( BringWindowToTop( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { hb_retnl( SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ) ); } и сделать тест: Function TestWnd Local ch := hb_gtinfo(HB_GTI_WINTITLE) Local hWnd1 := FindWindow(ch) Local hWnd2 := FindWindow('Паук') ? SETFOREGROUNDWINDOW(hWnd2) ? BringWindowToTop(hWnd2) Inkey(2) ? SETFOREGROUNDWINDOW(hWnd1) ? BringWindowToTop(hWnd1) return nil Запустить игрушку паук, и этот тест. Результат: ? SETFOREGROUNDWINDOW(hWnd1) возвращает 0, то есть не работает Похоже, здесь срабатывает та самая оговорка.

Oskar_AAA: Спасибо, за советы и участие. Обошелся проверкой на значение GetForeGroundWindow() >0 . Получилось то, что хотел в консоли

fokinal21: Надо очистить таблицу от пустых строк. Что-то из Harbour никак не получается... Может кто подскажет? Спасибо

Dima: fokinal21 пишет: Надо очистить таблицу от пустых строк Вопрос не очень понятен.

Dima: fokinal21 Может имелось в виду скрыть диапазон строк ?

fokinal21: Есть таблица в Excel, надо удалить пустые строки В моем частном случае дело упрощается тем, что их можно определить по пустым ячейкам первого столбца В vba это решается просто и понятно: Sub RowDel() LastRow = ActiveSheet.UsedRange.Row - 1 + ActiveSheet.UsedRange.Rows.Count Application.ScreenUpdating = False For r = LastRow To 1 Step -1 If Application.Rows(r).Columns(1).Value = "" Then Rows(r).Delete Next r End Sub Попытался перевести все это в Harbour и вот что получилось : Function RowDel() oExcel := CreateObject( "Excel.Application" ) oExcel:Workbooks:Open(Getfile()) oList := oExcel:Get( "ActiveSheet" ) oExcel:Visible("True") LastRow:= oList:UsedRange:Row-1 + oList:UsedRange:Rows:Count For r = LastRow To 1 Step -1 If oExcel:Rows(r):Columns(1):Value <>"" oExcel:Rows(r):Delete() endif Next r return при этом, если в vba прога срабатывает при Value = "", что логически верно, то в Harbour все работает при Value <>"" что совсем мне непонятно Это проверено на простой тестовой таблице - просто заполнил в первом столбце несколько ячеек не подряд Кроме этого vba спокойно глотает наличие чисел в части ячеек, Harbour падает в ошибку.

Петр: За такой перевод переводчик от технического редактора по рукам может получить Ближе к теме: вспоминайте, для чего предназначена функция Empty в hb, и countA в vba, а также посмотрите пример от MVP Dennis Wallentin в топике Range.Row Property (Excel) Sub Delete_Empty_Rows() 'This example deletes the empty rows from a selected range.

fokinal21: Петр пишет: вспоминайте, для чего предназначена функция Empty Спасибо! С Empty действительно все хорошо, но все же был интерес перевода готового примера в Harbour. Переведенный пример вполне рабочий (при текстовых заполнениях ячеек), но так и непонятно почему в Harbour все срабатывает при oExcel:Rows(r):Columns(1):Value <>"", может разъясните где логика порылась... А то как-то неспокойно

Петр: fokinal21 пишет: но все же был интерес перевода готового примера в Harbour Ну так переводите, только учтите, что при переводе Шекспира на русский используются правила русского языка. А при переводе этого примера на Harbour правильно было бы учитывать особенности vba, Excell и Harbour, а не только . на : поменять. [pre2]procedure main ? "" = "" ? "" = NIL ? "" <> "" ? "" <> NIL ? "" = 0[/pre2]

Oskar_AAA: Добрый день, коллеги Имеется файл с иерархической структурой строк, как определить уровень иерархии по строке. Пробовал такое: RowLevel=oSheet:Outline:ShowLevels RowLevels RowLevel=oAs:Row(Ni):Outline:RowLevels

Oskar_AAA: Решил: RowLevel=oSheet:Rows(Ni):OutlineLevel

Softlog86: Читаем / пишем .XLSX файлы из HARBOUR без использования EXCELL ! У меня всё получилось собрать . Примем на вооружение : https://github.com/FTrautwein/hblibxlsxwriter

fokinal21: Всем добрый вечер! Кусок кода: oExcel:=CreateObject( "Excel.Application" ) ? oExcel:hWnd oExcel:Quit() ? oExcel:hWnd В результате выводятся одинаковые значения. Почему, если Excel закрыт? Тоже самое происходит, если открыть файл и закрыть его вручную вместо Quit

Haz: fokinal21 пишет: Почему Потому что хендл окна присваиваивается при создании объекта и нет необходимости его актуализировать во время жизни объекта, т. к. это уже забота программиста. Еcли нужно что то с чемто сравнить, то нужно и проверить живо ли еще окно с таки хендлом

fokinal21: Haz пишет: Потому что хендл окна присваиваивается при создании объекта и нет необходимости его актуализировать во время жизни объекта Получается, что после Quit объект еще не умер? Если закрыть окно "крестиком" - тот же результат. Haz пишет: проверить живо ли еще окно с таки хендлом А как проверить? Этот результат появился после танцев вокруг поиска способа именно такой проверки.

Dima: fokinal21 пишет: oExcel:Quit() я после этого делаю так oWorkBook:=nil oSheet:=nil oExcel:=nil

Haz: fokinal21 пишет: А как проверить? Ну есть к примеру enumwindows которая возвращает список активных окон в системе. Возможно есть способ проще, типа похендлу получить статус окна... именно живо ли оно

Петр: Haz пишет: Возможно есть способ проще, типа похендлу получить статус окна Валидность хэндла обычно проверяют с использованием WinAPI функции IsWindow() В MiniGUI функция-враппер носит название IsWindowHandle(). if IsWindowHandle( oExcel:hWnd ) ...

fokinal21: oExcel :=CreateObject( "Excel.Application" ) hWnd:=oExcel:hWnd ? hWnd ? IsWindowHandle(hWnd) // Результаты: 462230 и .T. oExcel:Quit() ? hWnd ? IsWindowHandle(hWnd) // Результаты: 462230 и .T. *По рекомендации Dima oExcel:=nil ? hWnd ? IsWindowHandle(hWnd) // Результаты: 462230 и .T. // Итог: oExcel опять живее всех живых, несмотря на oExcel:Quit() и oExcel:=nil

Dima: fokinal21 пишет: *По рекомендации Dima oExcel:=nil ? hWnd ? IsWindowHandle(hWnd) // Результаты: 462230 и .T. // Итог: oExcel опять живее всех живых, несмотря на oExcel:Quit() и oExcel:=nil Ну тогда нужно так oExcel:Quit() oExcel:=nil ? hWnd:=oExcel:hWnd ? IsWindowHandle(hWnd) // Итог: результат в студию

Sergy: Dima пишет: oExcel:Quit() oExcel:=nil ? hWnd:=oExcel:hWnd ? IsWindowHandle(hWnd) // Итог: результат в студию Можно даже не компилировать - результатом будет ошибка времени исполнения, тк у переменной типа NIL не может быть свойства :hWnd А ноги у этой проблемы вот отсюда растут: http://clipper.borda.ru/?1-4-0-00001096-000-0-0-1440920410 Вот тут тоже обсуждали: http://clipper.borda.ru/?1-4-0-00000591-000-0-0-1317808661 Вот решение: http://clipper.borda.ru/?1-4-0-00000876-000-0-0-1373554002 [pre2] func Start_Excel() Local Res:=.f. #ifndef __XHARBOUR__ #xcommand TRY => BEGIN SEQUENCE WITH {|e| Break( e )} #xcommand CATCH [<!oErr!>] => RECOVER [USING <oErr>] <-oErr-> #endif TRY oExcel := GetActiveObject( "Excel.Application" ) oExcel:DisplayAlerts:=.f. Res:=.t. CATCH Res:=.f. TRY oExcel := CreateObject( "Excel.Application" ) Res:=.t. CATCH Res:=.f. END END Return Res [/pre2] Т.е. если процесс уже есть в памяти - использовать его, а не создавать новый.

fokinal21: В общем понятно, что процесс Excel закрывается только после закрытия вызвавшей его программы, как ни крути Quit - ами и nil - ами. И это значит, что попытки выяснить с помощью хендла закрыл юзер окно с табличкой или нет обречены на провал, а это и надо было мне сделать. Может кто проведет другим путем?

Dima: fokinal21 пишет: это значит, что попытки выяснить с помощью хендла закрыл юзер окно с табличкой или нет обречены на провал А зачем это контролировать ? Выбросил форму в Excel а дальше юзер что хочет с ней то и делает. У себя делаю примерно так: oExcel:DisplayAlerts:=.t. oExcel:Visible := .t. oSheet:Cells( 1, 1 ):select() //oSheet:Protect( "blabla" ) Showexcel(oExcel)

Haz: fokinal21 пишет: Может кто проведет другим путем? Да легко Суть в том что любое окно порождено конкретным процессом. Отслеживать хендл окна дело бесперспективное т. к. Винда использует повторное пернназначение (хендл закрытого окна может пллучтьб вновь созданное) Поэтому имеет смысл привязыватьсяименно к процессу еоторый это окно родил. И задача сводится к тому что бы определить жив ли сам процесс. Как определить? По алгоритму 1.зная окно можно найти процесс который его создал 2.зная процесс получить программу которая в нем выполняетя 3.и если это тот процесс и та программа то юзер ее еще не убил Ps в харбуре есть инструмент чтоб этот алгоритм проверить Будут вопросы пиши. На чтото я смогу ответить на что-то коллеги помогут

fokinal21: Haz пишет: Как определить? По алгоритму 1.зная окно можно найти процесс который его создал 2.зная процесс получить программу которая в нем выполняетя 3.и если это тот процесс и та программа то юзер ее еще не убил Пока на все один большой вопрос ? Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть.

Петр: fokinal21 пишет: Пока на все один большой вопрос ? Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть. Зачем это все прикладному программисту? fokinal21 пишет: В общем понятно, что процесс Excel закрывается только после закрытия вызвавшей его программы, как ни крути Quit - ами и nil - ами. И это значит, что попытки выяснить с помощью хендла закрыл юзер окно с табличкой или нет обречены на провал, а это и надо было мне сделать. Может кто проведет другим путем? oExсel:hWnd хранит хэндл главного окна oExсel (с классом 'XLMAIN'), как вы его собираетесь использовать для определения окна с табличкой, это еще вопрос. oExсel также имеет коллекцию Windows - "that represents all the windows in all the workbooks", вот я б с ней пробовал работать в вашей ситуации.

Haz: fokinal21 пишет: Пока на все один большой вопрос ? Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть. Вот тот самый небольшой пример. Показывает окна их класс и заголовки. В том числе если есть открытая книга в Excel то ее и покажет в списке [pre2] #include "common.ch" #include "i_winuser.ch" #define WM_GETTEXT 0x000D #define WM_SETTEXT 0x000C #define WM_GETTEXTLENGTH 0x000E Func main() local hWnd := 0 local aWin := {} local aChild := {} local hChildWindow := 0 local i := 0 local j := 0 local nLen := 0 local nLenCh := 0 REQUEST HB_LANG_RU866 HB_LANGSELECT("RU866") REQUEST HB_CODEPAGE_RU1251 hb_cdpSelect( "RU1251" ) aWin := EnumWindows() nLen := len( aWin ) for i := 1 to nLen aChild := EnumChild( aWin[ i ] ) nLenCh := LEN( aChild ) for j := 1 TO nLenCh ? aChild[j][2], aChild[ j ][3] end end return NIL Func EnumChild( hWin ) local aChild := {} EnumChildWindows( hWin, { |hChild, nLParam | AADD( aChild, { hChild, GetClassName( hChild ), GetChildWindowText(hChild) } ) , .T. }, 0 ) return aChild FUNCTION GetChildWindowText(hWnd ) LOCAL nLen, cText nLen := SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0) + 1 cText := Space( nLen) nLen := SendMessageString(hWnd, WM_GETTEXT, nLen, @cText) RETURN substr(cText,1,nLen) ********************************************************************************************************************************************** * ********************************************************************************************************************************************** #pragma BEGINDUMP #include <windows.h> #include "hbapi.h" #include "hbapiitm.h" #include <hbapi.h> #include <hbapiitm.h> #include <windows.h> void hb_evalBlock( PHB_ITEM pCodeBlock, ... ); static PHB_ITEM pCodeBlock = NULL; BOOL CALLBACK static EnumChildProc( HWND hWnd, LPARAM lParam ) { PHB_ITEM pHWnd = hb_itemPutNL( NULL, ( LONG ) hWnd ); PHB_ITEM pParam = hb_itemPutNL( NULL, ( LONG ) lParam ); if( pCodeBlock ) hb_evalBlock( pCodeBlock, pHWnd, pParam, 0 ); hb_itemRelease( pHWnd ); hb_itemRelease( pParam ); return hb_parl( -1 ); } HB_FUNC( ENUMCHILDWINDOWS ) { HWND hWnd = ( HWND ) hb_parnl( 1 ); LPARAM lParam = ( LPARAM ) hb_parnl( 3 ); pCodeBlock = hb_param( 2, HB_IT_BLOCK ); hb_retl( EnumChildWindows( hWnd, EnumChildProc, lParam ) ); pCodeBlock = NULL; } BOOL CALLBACK static EnumWinProc( HWND hWnd, LPARAM lParam ) { PHB_ITEM pHWnd = hb_itemPutNL( NULL, ( LONG ) hWnd ); PHB_ITEM pParam = hb_itemPutNL( NULL, ( LONG ) lParam ); if( pCodeBlock ) hb_evalBlock( pCodeBlock, pHWnd, pParam, 0 ); hb_itemRelease( pHWnd ); hb_itemRelease( pParam ); return TRUE; } static PHB_ITEM pArray; #if defined( __BORLANDC__ ) #pragma argsused #endif BOOL CALLBACK EnumWindowsProc( HWND hWnd, LPARAM lParam ) { PHB_ITEM pHWnd = hb_itemPutNL( NULL, ( LONG ) hWnd ); #if defined( __MINGW32__ ) UNREFERENCED_PARAMETER( lParam ); #endif hb_arrayAddForward( pArray, pHWnd ); hb_itemRelease( pHWnd ); return TRUE; } HB_FUNC ( ENUMWINDOWS ) { pArray = hb_itemArrayNew( 0 ); EnumWindows( ( WNDENUMPROC ) EnumWindowsProc, ( LPARAM ) 0 ); hb_itemReturnRelease( pArray ); pArray = NULL; } BOOL CALLBACK EnumThreadWndProc( HWND hWnd, LPARAM lParam ) { PHB_ITEM pHWnd = hb_itemPutNL( NULL, ( LONG ) hWnd ); #if defined( __MINGW32__ ) UNREFERENCED_PARAMETER( lParam ); #endif hb_arrayAddForward( pArray, pHWnd ); hb_itemRelease( pHWnd ); return TRUE; } HB_FUNC ( GETCLASSNAME ) { HWND hWnd = (HWND) hb_parnl( 1 ); TCHAR ClassName[ 1024 ]; GetClassName( hWnd, ClassName, sizeof (ClassName) / sizeof (TCHAR) ); hb_retc( ClassName ); } HB_FUNC( GETWINDOWTEXT ) { HWND hWnd = ( HWND ) hb_parnl( 1 ); int iLen = GetWindowTextLength( hWnd ); char * cText = ( char * ) hb_xgrab( iLen + 1 ); int iRet = GetWindowText( hWnd, ( LPSTR ) cText, iLen + 1 ); hb_retclen( cText, iRet ); hb_xfree( cText ); } HB_FUNC( SENDMESSAGE ) { hb_retnl( ( LONG ) SendMessage( ( HWND ) hb_parnl( 1 ), ( UINT ) hb_parni( 2 ), ( WPARAM ) hb_parnl( 3 ), ( LPARAM ) hb_parnl( 4 ) ) ); } HB_FUNC( SENDMESSAGESTRING ) { hb_retnl( ( LONG ) SendMessage( ( HWND ) hb_parnl( 1 ), ( UINT ) hb_parni( 2 ), ( WPARAM ) hb_parnl( 3 ), ( LPARAM ) ( LPSTR ) hb_parc( 4 ) ) ); } HB_FUNC ( POSTMESSAGE ) { hb_retl( (BOOL) PostMessage ( (HWND) hb_parnl (1), (UINT) hb_parni (2), (WPARAM) hb_parnl (3), (LPARAM) hb_parnl (4) ) ); } #pragma ENDDUMP [/pre2]

fokinal21: Всем спасибо за помощь и консультации! Haz пишет: Вот тот самый небольшой пример Буду, по возможности, разбираться с примером...

Dima: fokinal21 пишет: Буду, по возможности, разбираться с примером... Пример по ходу отображается не верно , там где есть [ i ] только без пробелов внутри скобок

SergKis: Dima пишет Пример по ходу отображается не верно тут [pre2] for i := 1 to nLen aChild := EnumChild( aWin[ i ] ) nLenCh := LEN( aChild ) for j := 1 TO nLenCh ? aChild[j][2], aChild[j][3] end end[/pre2]

Haz: SergKis пишет: тут Дима , Сергей , спасибо . Подправил [ и ]

Петр: [pre2] REQUEST HB_LANG_RU866 REQUEST HB_CODEPAGE_RU1251 procedure Main( p, m ) local oExcel, oWorkBook, oWindows local nI, nCount, w hb_LangSelect( "RU866" ) hb_cdpSelect( "RU1251" ) hb_default( @p, "/" ) hb_default( @m, "/m" ) if hb_LeftEqI( p, "/g" ) .or. hb_LeftEqI( p, "-g" ) oExcel := win_oleGetActiveObject( "Excel.Application" ) elseif hb_LeftEqI( p, "/c" ) .or. hb_LeftEqI( p, "-c" ) oExcel := win_oleCreateObject( "Excel.Application" ) else ? Upper( __FILE__ ), '[/G|/C] [/M]' ? ' /C - Create new Excel object' ? ' /G - Get existing object' ? ' /M - Merge instances [by default]' ? '' endif if oExcel != NIL IF hb_LeftEqI( m, "/m" ) .or. hb_LeftEqI( m, "-m" ) oExcel:MergeInstances := .T. else oExcel:MergeInstances := .F. endif ? oExcel:hwnd ? '---------' oWindows := oExcel:Windows() oWorkBook := oExcel:WorkBooks:Add() nCount := oWindows:Count // Note that the active window is always Windows[1] oWindows[1]:Caption := "xl#win#" + hb_NtoS( nCount ) for each w in oWindows ? w:caption ? w:hwnd next oExcel:Visible := .T. //oExcel:Quit() else ? "Error: MS Excel not available. [" + win_oleErrorText() + "]" endif return [/pre2] Программа консольная. Компилировать как-то так hbmk2 myexcel.prg -lhbwin Запускать myexcel /c /m myexcel /g myexcel /g myexcel /g Рекомендую посмотреть, проанализировать и сделать выводы Интересно будет посмотреть на результат для разных версий Excel P.S. Excel 2016 работает чудненько.

Dima: Петр пишет: P.S. Excel 2016 работает чудненько. На 2003 падает на oExcel:MergeInstances и закоментил пока , пересобрал , запустил с ключом /C и упал в цикле на ? w:hwnd

Петр: Dima пишет: На 2003 падает на oExcel:MergeInstances Настоящий Эксель начинается с 2013 Dima пишет: упал в цикле на ? w:hwnd Припоминаю, что где-то мы уже это обсуждали, у Ворда свойство hwnd есть, у Экселя нет. В 2007(?) вроде уже есть.

Dima: Петр пишет: Настоящий Эксель начинается с 2013 Кажется в примере не хватает проверки перед его запуском на версию офиса , впрочем это уже обсуждали в одной из тем , так что кому надо тот сам и допилит. PS У многих еще стоит XP и далеко не SP3 , так что заюзать могут офис только ниже 2010

Петр: Dima пишет: Кажется в примере не хватает проверки перед его запуском на версию офиса Можно добавить в любом удобном месте ? oExcel:version И танцевать от результата Excel 2003 - 11.0 Excel 2007 - 12.0 Excel 2010 - 14.0 Excel 2013 - 15.0 Excel 2016 - 16.0



полная версия страницы