Автор | Сообщение |
Dima
|
| |
Пост N: 2372
Зарегистрирован: 17.05.05
|
|
Отправлено: 21.05.12 16:52. Заголовок: Снова EXCEL (продолжение)
Ранее с Excel из Harbour ни когда не работал. Поставили тут задачу. У некоторых поставщиков есть определенные формы заказов. Набраны они в Excel. Сейчас народ руками заполняет эти формы и шлет по электронке поставщикам. Задача сводится к тому что бы в этих формах находить нужные коды товара и в нужной ячейке проставлять заказ. Может ткнет кто носом с чего начать что бы не напороться на грабли. Спасибо Сами формы тут http://zalil.ru/33279066
|
|
|
Ответов - 300
, стр:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
All
[только новые]
|
|
Haz
|
| |
Пост N: 1087
Зарегистрирован: 20.02.11
|
|
Отправлено: 15.04.17 22:35. Заголовок: fokinal21 пишет: А ..
fokinal21 пишет: Ну есть к примеру enumwindows которая возвращает список активных окон в системе. Возможно есть способ проще, типа похендлу получить статус окна... именно живо ли оно
|
|
|
Петр
|
| постоянный участник
|
Пост N: 1441
Зарегистрирован: 09.10.06
|
|
Отправлено: 15.04.17 23:47. Заголовок: Haz пишет: Возможн..
Haz пишет: цитата: | Возможно есть способ проще, типа похендлу получить статус окна |
| Валидность хэндла обычно проверяют с использованием WinAPI функции IsWindow() В MiniGUI функция-враппер носит название IsWindowHandle(). if IsWindowHandle( oExcel:hWnd ) ...
|
|
|
fokinal21
|
| |
Пост N: 22
Зарегистрирован: 22.09.13
|
|
Отправлено: 16.04.17 11:19. Заголовок: oExcel ..
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
|
| |
Пост N: 6361
Зарегистрирован: 17.05.05
|
|
Отправлено: 16.04.17 12:22. Заголовок: fokinal21 пишет: *П..
fokinal21 пишет: цитата: | *По рекомендации Dima oExcel:=nil ? hWnd ? IsWindowHandle(hWnd) // Результаты: 462230 и .T. // Итог: oExcel опять живее всех живых, несмотря на oExcel:Quit() и oExcel:=nil |
| Ну тогда нужно так oExcel:Quit() oExcel:=nil ? hWnd:=oExcel:hWnd ? IsWindowHandle(hWnd) // Итог: результат в студию
|
|
|
Sergy
|
| |
Пост N: 523
Зарегистрирован: 08.07.06
|
|
Отправлено: 16.04.17 12:33. Заголовок: Dima пишет: oExcel:..
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 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 Т.е. если процесс уже есть в памяти - использовать его, а не создавать новый.
|
|
|
fokinal21
|
| |
Пост N: 23
Зарегистрирован: 22.09.13
|
|
Отправлено: 16.04.17 16:36. Заголовок: В общем понятно, что..
В общем понятно, что процесс Excel закрывается только после закрытия вызвавшей его программы, как ни крути Quit - ами и nil - ами. И это значит, что попытки выяснить с помощью хендла закрыл юзер окно с табличкой или нет обречены на провал, а это и надо было мне сделать. Может кто проведет другим путем?
|
|
|
Dima
|
| |
Пост N: 6364
Зарегистрирован: 17.05.05
|
|
Отправлено: 16.04.17 16:43. Заголовок: fokinal21 пишет: эт..
fokinal21 пишет: цитата: | это значит, что попытки выяснить с помощью хендла закрыл юзер окно с табличкой или нет обречены на провал |
| А зачем это контролировать ? Выбросил форму в Excel а дальше юзер что хочет с ней то и делает. У себя делаю примерно так: oExcel:DisplayAlerts:=.t. oExcel:Visible := .t. oSheet:Cells( 1, 1 ):select() //oSheet:Protect( "blabla" ) Showexcel(oExcel)
|
|
|
Haz
|
| |
Пост N: 1088
Зарегистрирован: 20.02.11
|
|
Отправлено: 16.04.17 18:42. Заголовок: fokinal21 пишет: Мо..
fokinal21 пишет: цитата: | Может кто проведет другим путем? |
| Да легко Суть в том что любое окно порождено конкретным процессом. Отслеживать хендл окна дело бесперспективное т. к. Винда использует повторное пернназначение (хендл закрытого окна может пллучтьб вновь созданное) Поэтому имеет смысл привязыватьсяименно к процессу еоторый это окно родил. И задача сводится к тому что бы определить жив ли сам процесс. Как определить? По алгоритму 1.зная окно можно найти процесс который его создал 2.зная процесс получить программу которая в нем выполняетя 3.и если это тот процесс и та программа то юзер ее еще не убил Ps в харбуре есть инструмент чтоб этот алгоритм проверить Будут вопросы пиши. На чтото я смогу ответить на что-то коллеги помогут
|
|
|
fokinal21
|
| |
Пост N: 24
Зарегистрирован: 22.09.13
|
|
Отправлено: 17.04.17 09:49. Заголовок: Haz пишет: Как опр..
Haz пишет: цитата: | Как определить? По алгоритму 1.зная окно можно найти процесс который его создал 2.зная процесс получить программу которая в нем выполняетя 3.и если это тот процесс и та программа то юзер ее еще не убил |
| Пока на все один большой вопрос ? Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть.
|
|
|
Петр
|
| постоянный участник
|
Пост N: 1443
Зарегистрирован: 09.10.06
|
|
Отправлено: 17.04.17 11:58. Заголовок: fokinal21 пишет: По..
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
|
| |
Пост N: 1089
Зарегистрирован: 20.02.11
|
|
Отправлено: 18.04.17 11:13. Заголовок: fokinal21 пишет: По..
fokinal21 пишет: цитата: | Пока на все один большой вопрос ? Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть. |
| Вот тот самый небольшой пример. Показывает окна их класс и заголовки. В том числе если есть открытая книга в Excel то ее и покажет в списке #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
|
|
|
|
fokinal21
|
| |
Пост N: 25
Зарегистрирован: 22.09.13
|
|
Отправлено: 18.04.17 12:15. Заголовок: Всем спасибо за помо..
Всем спасибо за помощь и консультации! Haz пишет: цитата: | Вот тот самый небольшой пример |
| Буду, по возможности, разбираться с примером...
|
|
|
Dima
|
| |
Пост N: 6368
Зарегистрирован: 17.05.05
|
|
Отправлено: 18.04.17 12:37. Заголовок: fokinal21 пишет: Бу..
fokinal21 пишет: цитата: | Буду, по возможности, разбираться с примером... |
| Пример по ходу отображается не верно , там где есть [ i ] только без пробелов внутри скобок
|
|
|
SergKis
|
| постоянный участник
|
Пост N: 1410
Зарегистрирован: 17.02.12
|
|
Отправлено: 18.04.17 12:42. Заголовок: Dima пишет Пример по..
Dima пишет цитата: | Пример по ходу отображается не верно |
| тут 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
|
|
|
Haz
|
| |
Пост N: 1090
Зарегистрирован: 20.02.11
|
|
Отправлено: 18.04.17 13:36. Заголовок: SergKis пишет: тут ..
SergKis пишет: Дима , Сергей , спасибо . Подправил [ и ]
|
|
|
Петр
|
| постоянный участник
|
Пост N: 1445
Зарегистрирован: 09.10.06
|
|
Отправлено: 18.04.17 15:48. Заголовок: REQUEST HB_LANG_RU8..
цитата: | 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 |
| Программа консольная. Компилировать как-то так hbmk2 myexcel.prg -lhbwin Запускать myexcel /c /m myexcel /g myexcel /g myexcel /g Рекомендую посмотреть, проанализировать и сделать выводы Интересно будет посмотреть на результат для разных версий Excel P.S. Excel 2016 работает чудненько.
|
|
|
Dima
|
| |
Пост N: 6372
Зарегистрирован: 17.05.05
|
|
Отправлено: 18.04.17 16:26. Заголовок: Петр пишет: P.S. Ex..
Петр пишет: цитата: | P.S. Excel 2016 работает чудненько. |
| На 2003 падает на oExcel:MergeInstances и закоментил пока , пересобрал , запустил с ключом /C и упал в цикле на ? w:hwnd
|
|
|
Петр
|
| постоянный участник
|
Пост N: 1447
Зарегистрирован: 09.10.06
|
|
Отправлено: 18.04.17 16:38. Заголовок: Dima пишет: На 2003..
Dima пишет: цитата: | На 2003 падает на oExcel:MergeInstances |
| Настоящий Эксель начинается с 2013 Dima пишет: Припоминаю, что где-то мы уже это обсуждали, у Ворда свойство hwnd есть, у Экселя нет. В 2007(?) вроде уже есть.
|
|
|
Dima
|
| |
Пост N: 6374
Зарегистрирован: 17.05.05
|
|
Отправлено: 18.04.17 21:21. Заголовок: Петр пишет: Настоящ..
Петр пишет: цитата: | Настоящий Эксель начинается с 2013 |
| Кажется в примере не хватает проверки перед его запуском на версию офиса , впрочем это уже обсуждали в одной из тем , так что кому надо тот сам и допилит. PS У многих еще стоит XP и далеко не SP3 , так что заюзать могут офис только ниже 2010
|
|
|
Петр
|
| постоянный участник
|
Пост N: 1448
Зарегистрирован: 09.10.06
|
|
Отправлено: 18.04.17 22:12. Заголовок: Dima пишет: Кажется..
Dima пишет: цитата: | Кажется в примере не хватает проверки перед его запуском на версию офиса |
| Можно добавить в любом удобном месте ? oExcel:version И танцевать от результата Excel 2003 - 11.0 Excel 2007 - 12.0 Excel 2010 - 14.0 Excel 2013 - 15.0 Excel 2016 - 16.0
|
|
|
Ответов - 300
, стр:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
All
[только новые]
|
|