<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; AHK: Cумма прописью (в любом окне)]]></title>
	<link rel="self" href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=12562&amp;type=atom" />
	<updated>2017-03-31T13:15:34Z</updated>
	<generator>PunBB</generator>
	<id>https://forum.script-coding.com/viewtopic.php?id=12562</id>
		<entry>
			<title type="html"><![CDATA[Re: AHK: Cумма прописью (в любом окне)]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=114456#p114456" />
			<content type="html"><![CDATA[<p>Одна десятая секунды ожидания наполнения буфера это нонсенс - всегда орлянка. Система занята не одними вашими нуждами. Поставьте ожидание полсекунды-секунду и с божьей помощью это будет работать.</p>]]></content>
			<author>
				<name><![CDATA[Krot66]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=30687</uri>
			</author>
			<updated>2017-03-31T13:15:34Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=114456#p114456</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: Cумма прописью (в любом окне)]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=114452#p114452" />
			<content type="html"><![CDATA[<p>Тестирование затянулось... Вся проблема в том, что с локальными приложениями достаточно надежно работают все варианты. Когда дело доходит до опубликованных удаленных приложений, то работоспособность команд, эмулирующих клавиатурные нажатия становится точно такой же хреновой как и в других скриптовых языках. К сожалению, я не вижу способа обеспечить работу скрипта с самыми различными окнами без использования этих долбанных Send-ов. Поэтому, долгие эксперименты привели меня к такому коду (<strong>stealzy</strong>, я многое содрал у Вас):<br /></p><div class="codebox"><pre><code>; Сумма прописью {Ctrl Shift W}
Hotkey % &quot;+^&quot; Format(&quot;vk{:02x}&quot;, GetKeyVK(&quot;W&quot;)), CopyConvertPaste
Return

CopyConvertPaste(){
	SetKeyDelay 20, 20
	tmp := ClipboardAll
	Clipboard := &quot;&quot;
	Send, ^{Ins}
	ClipWait,.1,1
	If ErrorLevel
		Return
	ctext := Clipboard ; очищаем текст от форматирования
	;Извлекаем число из выделенного текста, например: &quot;ИТОГО: 2 431 234 012, 31 руб.&quot;
	ctext := RegExReplace(ctext,&quot;=|,&quot;, &quot;.&quot;)
	ctext := RegExReplace(ctext,&quot;[^\d\.]&quot;)
	ctext := RegExReplace(ctext,&quot;\.$&quot;)
	If (RegExMatch(ctext,&quot;\d+&quot;)) {
		Clipboard := &quot; (&quot; . Sum2Words(ctext, 2) . &quot;)&quot;
		Send, {Right}
		Sleep 400
		Send, +{Ins}
		Sleep 200
	}
	Clipboard := tmp
}
</code></pre></div><p>Сразу отвечу на вероятные возражения:<br />1. SetKeyDelay использование Sleep не отменяет. Проверено. Да и в доках, если внимательно читать, тоже написано.<br />2. SendPlay работает как и SendInput через пень колоду.<br />3. SendMode Input делает единственно рабочую команду Send такой же тупой как SendInput и SendPlay (что, в общем, так же написано в документации)</p>]]></content>
			<author>
				<name><![CDATA[mozers]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=4112</uri>
			</author>
			<updated>2017-03-31T11:51:29Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=114452#p114452</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: Cумма прописью (в любом окне)]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=114215#p114215" />
			<content type="html"><![CDATA[<p><span style="color: green">Обсуждение способов присваивания переменной переехало в <a href="http://forum.script-coding.com/viewtopic.php?id=9952">соответствующую тему</a>.</span></p>]]></content>
			<author>
				<name><![CDATA[ypppu]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=5974</uri>
			</author>
			<updated>2017-03-26T10:59:45Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=114215#p114215</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: Cумма прописью (в любом окне)]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=114213#p114213" />
			<content type="html"><![CDATA[<p><strong>mozers</strong>, именно так у меня и глючил SendInput, вероятно это касается любых сочетаний с модификаторами.<br />SetKeyDelay как раз, чтобы не писать Sleep`ы.<br />Добавил в код время и обработку ErrorLevel ClipWait - не зря же он там.</p>]]></content>
			<author>
				<name><![CDATA[stealzy]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=31937</uri>
			</author>
			<updated>2017-03-26T10:14:49Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=114213#p114213</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: Cумма прописью (в любом окне)]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=114164#p114164" />
			<content type="html"><![CDATA[<div class="quotebox"><blockquote><p>зачем тут задержки? Надо бы SendInput использовать.</p></blockquote></div><p>Без задержек, курсор не успевает подвинуться <span style="color: blue">Send,{Right}</span> и убрать выделение и тогда <span class="bbu">вместо</span> выделенного текста вставляется не результат преобразования, а предыдущее содержимое буфера обмена (это значит не успело сработать <span style="color: blue">Send,+{Ins}</span>). Стабильно такое происходит с &quot;тормознутыми&quot; окнами (например, с окнами удаленных опубликованных приложений).<br /><span style="color: blue">SendInput,+{Ins}</span> у меня почему то периодически &quot;глючит&quot; - выводит текст &quot;<span style="color: blue">+{Ins}</span>&quot; как будто я включил режим Raw =&gt; Я решил отказаться от использования этой &quot;глюкавой&quot; директивы.<br /></p><div class="quotebox"><blockquote><p>Или так:</p></blockquote></div><p>Спасибо! Буду тестировать.</p><p><strong>stealzy</strong><br /></p><div class="quotebox"><blockquote><p>Чтобы бухи вслух по слогам читали что-ли lol?</p></blockquote></div><p>Для этой поделки - действительно излишне. Просто хотелось использовать типовой механизм для всех подобных скриптов.<br /></p><div class="quotebox"><blockquote><p>По моей практике лучший метод отправки нажатий - Input, для сочетаний с Ctrl самый надежный - Play.</p></blockquote></div><p>Спасибо за подсказку и код! Буду тестировать.</p><br /><div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header" data-lang-open="открыть спойлер" data-lang-close="скрыть спойлер"><strong>+</strong>&nbsp;открыть спойлер</div><div class="fancy_spoiler"><p>Уважаемые модераторы!<br />Я крайне извиняюсь что моя невольно брошенная фраза разбила данный топик на 2 разных темы.</p></div></div>]]></content>
			<author>
				<name><![CDATA[mozers]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=4112</uri>
			</author>
			<updated>2017-03-26T09:51:44Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=114164#p114164</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: Cумма прописью (в любом окне)]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=114135#p114135" />
			<content type="html"><![CDATA[<div class="quotebox"><blockquote><p>в MsgBox выводить</p></blockquote></div><p>Чтобы бухи вслух по слогам читали что-ли <img src="//forum.script-coding.com/img/smilies/lol.png" width="15" height="15" />?<br />Если кому и понадобится число прописью, то исключительно в редактируемом поле. В нем с текстом и работают.<br />По моей практике лучший метод отправки нажатий - Input, для сочетаний с Ctrl самый надежный - Play.<br /></p><div class="codebox"><pre><code>Hotkey % &quot;+^&quot; Format(&quot;vk{:02x}&quot;, GetKeyVK(&quot;W&quot;)), CopyConvertSum2WordsPaste
Return

CopyConvertSum2WordsPaste() {
	SendMode Input
	SetKeyDelay 20, 20
	tmpClip := ClipboardAll, Clipboard := &quot;&quot;
	SendPlay ^{Ins}
	ClipWait,.1,1
	If ErrorLevel
		Return
	ctext := Clipboard ; очищаем текст от форматирования
	;Извлекаем число из выделенного текста, например: &quot;ИТОГО: 2 431 234 012, 31 руб.&quot;
	ctext := RegExReplace(ctext,&quot;=|,&quot;, &quot;.&quot;)
	ctext := RegExReplace(ctext,&quot;[^\d\.]&quot;)
	ctext := RegExReplace(ctext,&quot;\.$&quot;)
	If (RegExMatch(ctext,&quot;\d+&quot;)) {
		Clipboard := &quot; (&quot; . Sum2Words(ctext, 2) . &quot;)&quot;
		Send {Right}
		SendPlay +{Ins}
	}
	Clipboard := tmpClip
}</code></pre></div>]]></content>
			<author>
				<name><![CDATA[stealzy]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=31937</uri>
			</author>
			<updated>2017-03-26T05:39:42Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=114135#p114135</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: AHK: Cумма прописью (в любом окне)]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=114105#p114105" />
			<content type="html"><![CDATA[<div class="quotebox"><cite>mozers пишет:</cite><blockquote><p> как определить нередактируемый текст. Ну чтобы если такое случается, результат вычислений не в текст вставлять, а в MsgBox выводить.</p></blockquote></div><p>Вместо Send, ^{Ins} что ли?<br />Кстати,<br /></p><div class="codebox"><pre><code>ctext := RegExReplace(ctext,&quot;[^\d\.]&quot;)
ctext := RegExReplace(ctext,&quot;\.$&quot;)
If (RegExMatch(ctext,&quot;\d+&quot;)) {
	Clipboard := &quot; (&quot; . Sum2Words(ctext, 2) . &quot;)&quot;
	Send, {Right}
	Sleep 200
	Send, +{Ins}
	Sleep 200
}</code></pre></div><p>зачем тут задержки? Надо бы SendInput использовать. Или так:<br /></p><div class="codebox"><pre><code>ctext := RegExReplace(ctext,&quot;[^\d.]|\.$&quot;)
If ctext is number {
	SendInput, {Right}
	Control EditPaste, % ctext,, A
}</code></pre></div><p>Ещё в начало кода стоит добавить для скорости:</p><div class="codebox"><pre><code>#NoEnv
ListLines, Off
#KeyHistory, 0
SetBatchLines,-1</code></pre></div>]]></content>
			<author>
				<name><![CDATA[Flasher]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=27593</uri>
			</author>
			<updated>2017-03-25T20:34:57Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=114105#p114105</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[AHK: Cумма прописью (в любом окне)]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=114098#p114098" />
			<content type="html"><![CDATA[<p>Классический бухгалтерский функционал: По Ctrl+Shift+W добавляет к выделенной сумме в числовом виде строку, описывающую эту сумму прописью в рублях и копейках. Копейки можно выводить как прописью так и числом (с лидирующим нулём при необходимости).<br />Работает в окнах любых приложений (как локальных, так и опубликованных через Citrix). Проверен на Win7 и Win10.<br /></p><div class="codebox"><pre><code>; Сумма прописью
^+vk57:: ; {Ctrl Shift W}
tmp := ClipboardAll
Clipboard := &quot;&quot;
Send, ^{Ins}
ClipWait, , 1
ctext := Clipboard ; очищаем текст от форматирования
;Извлекаем число из выделенного текста, например: &quot;ИТОГО: 2 431 234 012, 31 руб.&quot;
ctext := RegExReplace(ctext,&quot;=|,&quot;, &quot;.&quot;)
ctext := RegExReplace(ctext,&quot;[^\d\.]&quot;)
ctext := RegExReplace(ctext,&quot;\.$&quot;)
If (RegExMatch(ctext,&quot;\d+&quot;)) {
	Clipboard := &quot; (&quot; . Sum2Words(ctext, 2) . &quot;)&quot;
	Send, {Right}
	Sleep 200
	Send, +{Ins}
	Sleep 200
}
Clipboard := tmp
Return

;Использован прототип (VBA) http://www.script-coding.com/SumInWords.zip
;Функция возвращает сумму прописью в указанной валюте.
;Первый аргумент - число (сумма).
;Второй аргумент - формат вывода копеек:
;1 - копейки числом,
;2 - копейки числом с лидирующим нулём при необходимости,
;любое другое число - копейки прописью.
Sum2Words(sum, kop) {
	;Округление до двух знаков после запятой
	sum := Round(Abs(sum), 2)
	words := []

	;Миллиард
	num := Floor(sum/1000000000)
	If (num &gt; 0) {
		words.Push(Rest2Words(num, True))
		words.Push([&quot;миллиардов&quot;,&quot;миллиарда&quot;,&quot;миллиард&quot;][CaseOfWord(num)])
	}
	sum -= num*1000000000

	;Миллион
	num := Floor(sum/1000000)
	If (num &gt; 0) {
		words.Push(Rest2Words(num, True))
		words.Push([&quot;миллионов&quot;,&quot;миллиона&quot;,&quot;миллион&quot;][CaseOfWord(num)])
	}
	sum -= num*1000000

	;Тысяча
	num := Floor(sum/1000)
	If (num &gt; 0) {
		words.Push(Rest2Words(num, False))
		words.Push([&quot;тысяч&quot;,&quot;тысячи&quot;,&quot;тысяча&quot;][CaseOfWord(num)])
	}
	sum -= num*1000

	;Рублей
	num := Floor(sum)
	If (num &gt; 0) {
		words.Push(Rest2Words(num, True))
		words.Push([&quot;рублей&quot;,&quot;рубля&quot;,&quot;рубль&quot;][CaseOfWord(num)])
	}
	sum -= num

	;Копеек
	num := Round(sum*100)
	If (kop = 1) { ; числом
		words.Push(num)
	}
	Else If (kop = 2) { ; числом с лидирующим 0
		StringRight, num, % &quot;0&quot; . num, 2
		words.Push(num)
	}
	Else { ; прописью
		words.Push(Rest2Words(num, False))
	}
	words.Push([&quot;копеек&quot;,&quot;копейки&quot;,&quot;копейка&quot;][CaseOfWord(num)])

	; Склеиваем все слова в одну строку
	words := Join(words, &quot; &quot;)

	;С заглавной буквы
	StringLeft, firstChar, words, 1
	StringUpper, firstChar, firstChar
	StringRight, otherChars, words, StrLen(words)-1

	Return firstChar . otherChars
}

;Функция возвращает индекс в массиве названий разряда числа.
;Аргумент - целое положительное число, меньшее тысячи.
CaseOfWord(num){
	StringRight, tens, num, 2    ;Десятки (два последних знака)
	If (tens &lt; 11 Or tens &gt; 19) {
		StringRight, unitys, num, 1  ;Единицы (один последний знак)
		If unitys = 1
			Return 3
		Else If unitys between 2 and 4
			Return 2
	}
	Return 1
}

;Функция возвращает число прописью.
;Первый аргумент - целое положительное число, меньшее тысячи.
;Второй аргумент - род числа (True - мужской, False - женский, для тысяч и копеек).
Rest2Words(rest, gender){
	rest := Abs(rest)
	If ((rest &lt;= 0) Or (rest &gt; 999)) {
		Return &quot;ноль&quot;
	}
	words := []

	;Сотни
	num := Floor(rest / 100)
	If (num &gt; 0) {
		words.Push([&quot;сто&quot;,&quot;двести&quot;,&quot;триста&quot;,&quot;четыреста&quot;,&quot;пятьсот&quot;,&quot;шестьсот&quot;,&quot;семьсот&quot;,&quot;восемьсот&quot;,&quot;девятьсот&quot;][num])
	}
	rest -= num*100

	;Десятки
	num := Floor(rest/10)
	If (num &gt; 1) {
		words.Push([&quot;двадцать&quot;,&quot;тридцать&quot;,&quot;сорок&quot;,&quot;пятьдесят&quot;,&quot;шестьдесят&quot;,&quot;семьдесят&quot;,&quot;восемьдесят&quot;,&quot;девяносто&quot;][num-1])
		rest -= num*10
	}
	Else If (num = 1) {
		words.Push([&quot;десять&quot;,&quot;одиннадцать&quot;,&quot;двенадцать&quot;,&quot;тринадцать&quot;,&quot;четырнадцать&quot;,&quot;пятнадцать&quot;,&quot;шестнадцать&quot;,&quot;семнадцать&quot;,&quot;восемнадцать&quot;,&quot;девятнадцать&quot;][rest-9])
		rest := 0
	}

	;Единицы
	If (rest &gt; 0) {
		If (rest = 1) {
			words.Push(gender ? &quot;один&quot; : &quot;одна&quot;)
		}
		Else If (rest = 2) {
			words.Push(gender ? &quot;два&quot; : &quot;две&quot;)
		}
		Else {
			words.Push([&quot;три&quot;,&quot;четыре&quot;,&quot;пять&quot;,&quot;шесть&quot;,&quot;семь&quot;,&quot;восемь&quot;,&quot;девять&quot;][rest-2])
		}
	}

	Return Join(words, &quot; &quot;)
}

; Возвращает склеенный в одну строку массив Array (с использованием разделителя Sep)
Join(array, sep) {
	for k, v in array
		out .= sep . v
	Return SubStr(out, 1+StrLen(sep))
}</code></pre></div><p>В AHK я - новичок. Не понимаю недоделанности некоторых общеупотребительных операторов, например, того же <span style="color: blue">If</span>. Конечно, привыкнуть к этому можно, но такие несуразности бросаются в глаза и создают не решаемые логическим путем глюки...<br />В общем, буду очень благодарен за советы и рекомендации по скрипту.<br />Интересует не сколько расширение функциональности, сколько правильность и корректность использованных функций, рефакторинг кода.</p><p>2<strong>All</strong><br />Пожалуйста, обратите внимание на начальный маленький блок получения и вставки текста. Нет замечаний? Просто мне кажется это - единственно правильный подход. Все другие (в т.ч. WinAPI) не универсальны (не со всеми окнами работать будут).<br />Может быть кто придумает как определить нередактируемый текст. Ну чтобы если такое случается, результат вычислений не в текст вставлять, а в MsgBox выводить. Вариант с вырезанием выделенного текста в буфер (если прокатило - значит - редактируемый) и последующей его вставкой знаю, но не нравится, поскольку надо добавлять кучу доп.кода чтобы содержимое буфера обмена не перекорежило.</p>]]></content>
			<author>
				<name><![CDATA[mozers]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=4112</uri>
			</author>
			<updated>2017-03-25T18:42:08Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=114098#p114098</id>
		</entry>
</feed>
