1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
'Begin Description
'Вставка текстового объекта (текстового блока) в окно результатов SPSS через
'метод SendKeys (эмуляция нажатия клавиш), вызовом меню Insert>Text.
'End Description

' Проверено: SPSS 15.0.0. В английской версии. Скрипт должен запускаться при включенной английской
' раскладке; пока скрипт работает - мышью не двигать (можно потерять фокус окна) - специфика работы SendKeys - примеч. перев.
Sub Main
	Dim objOutput As ISpssOutputDoc

	If objSpssApp.Documents.OutputDocCount = 0 Then 
		objSpssApp.NewOutputDoc
	End If
	
	Set objOutput = objSpssApp.GetDesignatedOutputDoc
	
	'******************************************
	'демонстрация работы процедур InsertText и SetCurrentItem
	
	Call SetCurrentItem (objOutput, objOutput.Items.Count - 1)
	InsertText objOutput, "Это первый вновь вставленный блок текста."
	
	Call SetCurrentItem (objOutput, objOutput.Items.Count - 1)
	InsertText objOutput, "Это второй вновь вставленный блок текста."
	
	Call SetCurrentItem (objOutput, 1)
	InsertText objOutput, "Это третий блок, вставленный после блока № 1."
	
	'Заметьте, что вызов процедуры SetCurrentItem с недопустимым аргументом приведёт к тому, что текущим будет объявлен последний (или первый) объект.
	Call SetCurrentItem (objOutput, objOutput.Items.Count + 1)
	InsertText objOutput, "Текстовый блок будет вставлен в конец документа " & vbCrLf _
		& "из-за ошибочного аргумента.  " & vbCrLf _
		& "Заметьте, что текстовый блок с несколькими строками может не  " & vbCrLf _
		& "отображаться полностью, пока не будет отмасштабирован. "
		
	Dim i As Long

	'если текстовый блок включает более одной строки, может потребоваться масштабирование.
	i = GetCurrentItem(objOutput)
	If i >= 0 Then
		With objOutput.Items.GetItem(i)
			'если это не текстовый объект, то этот не тот объект, что мы только что вставили (см. код выше)...
			If .SPSSType = SPSSText Then
				'умножим исходную высоту блока на число строк
				.Height = 4 * .Height	'можно использовать константу, разумеется
			End If
		End With
	End If
End Sub


'Добавляет новый текстовый блок после текущего (выделенного) объекта выдачи
'Требует: наличия процедуры SetCurrentItem и функции GetCurrentItem
Sub InsertText(objOutput As ISpssOutputDoc, strText As String)
	
	'******************************************
	'Используйте SetCurrentItem для позиционирования вставляемого блока текста.
	'Эта процедура делает нужный объект текущим.
	'InsertText вставляет текст после текущего объекта.
	'Чтобы гарантированно делать текущим последний объект в выдаче, снимите комментарий со следующей строки:
	'Call SetCurrentItem (objOutput, objOutput.Items.Count - 1)
	
	'******************************************
	'Добавление нового текстового блока
	
	'Установка видимости окна результатов приводит также к тому, что окно выходит на передний план
	' (получает фокус), так что передаваемые SendKeys клавиши будут "нажиматься" в нужном окне.
	objOutput.Visible = True

	'Отсылка клавиш для использования меню Insert>Text
	SendKeys "%IX"	'в версии 7.5.2 используйте use "%IX~"
	
	'******************************************
	'Добавление текста в созданный блок
	
	'Вставленный объект получит статус текущего... если немного подождать.
	Wait 1	'Дадим программе одну секунду, прежде, чем обращаться к текущему объекту
	i = GetCurrentItem(objOutput)
	If i >= 0 Then
		Set objItem = objOutput.Items.GetItem(i)
		If objItem.SPSSType = SPSSText Then
			Set objText = objItem.ActivateText
			'Если в блоке уже есть текст, значит, мы обратились не к тому объекту: проверим.
			If objText.Text = "" Then
				objText.Text = strText
			End If
			objItem.Deactivate
		End If
	End If
End Sub


'парная процедура для GetCurrentItem
Sub SetCurrentItem(objOutput As ISpssOutputDoc, ByVal lngItem As Long)
	
	On Error Resume Next
	'игнорируем ошибки
	
	Dim objItems As ISpssItems
	Dim lngCount As Long
	Dim i As Long

	Set objItems = objOutput.Items
	lngCount = objItems.Count
	
	'В случае проблем с переданным аргументом, приводим его к допустимому значению:
	'устанавливаем указатель на первый или последний объект. Эту часть процедуры можно
	'модифицировать, если в случае ошибки требуется какое-то другое поведение скрипта.
	i = lngItem
	If (i >= lngCount) Then i = lngCount - 1
	If (i < 0) Then i = 0
	
	objItems.GetItem(i).Current = True
	'Debug.Print "Номер объекта: " & lngItem
End Sub


'парная функция для SetCurrentItem
Function GetCurrentItem(objOutput As ISpssOutputDoc) As Long
	'функция возвращает номер текущего объекта
	'возвращается отрицательно число в случае, если объектов не найдено, либо возникла иная ошибка
	'процедура, вызывающая функцию, должна убедиться, что результат функции валидный (>= 0) перед дальнейшим
	'использованием результатов
	
	On Error GoTo ErrorHandler
	
	Dim objItems As ISpssItems
	Dim objItem As ISpssItem
	Dim i As Long
	
	Set objItems = objOutput.Items
	'высока вероятность, что текущий объект будет последним, поэтому поиск текущего начинаем с конца
	For i = objItems.Count - 1 To 0 Step -1
		If objItems.GetItem(i).Current Then
			GetCurrentItem = i
			Exit Function
		End If
	Next
	
ErrorHandler:	
	'не нашли объекты, или какая-то другая проблема возникла
	GetCurrentItem = -1
	
End Function