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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
'Код решения: 100008929 (SPSS AnswerNet)
'ПО:  SPSS Base
'Тема: автоматизация вращения мобильных таблиц (pivoting)

'Описание:.
'Я знаю, как можно менять структуру (вращать) мобильную таблицу (Pivot Table) вручную: двойной щелчок мышью для активации,
'затем перетаскиваем иконку размерности (например, "Statistics" или "Variables") в нужную размерность трея вращения (Pivoting Tray).
'Можно ли сделать такую же операцию через скрипт?

'Ответ.
'Да, и приводимая подпрограмма "PivotDimensionByName" упростит эту задачу.
'Сохраните порцию кода, обозначенную ниже в текстовый файл, и назовите его, скажем, "PivotDimensionByNameDemo.sbs".

'Создайте мобильную таблицу с размерностью "Statistics" (создаётся, скажем, процедурой Correlations или GLM). Выделите её.
'Далее либо откройте скрипт "PivotDimensionByNameDemo.sbs" в редакторе скриптов и запустите его, либо
'воспользуйтесь меню Utilities->Run Script для запуска того же скрипта.

'Вообще, эта подпрограмма может быть вызвана для вращения размерности с любым именем, может осуществлять поиск
'размерности с заданным именем в слоях, в строках, в столбцах (или во всех этих измерениях). Когда находится нужная размерность,
'возможно её вращение, опять же, в слои, в строки или в столбцы, со вставкой на первое место внутри измерения, на последнее, либо
'в заданную промежуточную позицию.

'Перевод: А. Балабанов, 24.11.2008.
'Проверено: SPSS 15.0.1.1. Добавлены строки с комментариями '### в функциях FindLayerDimension, FindRowDimension, FindColumnDimension,
' иначе в случае отсутствия нужной размерности они возвращали ссылку на другую (первую из имеющихся) размерность.


'Для практического использования измените приведённую ниже процедуру Sub Main в соответствие со своими потребностями.

'Приводимая ниже Sub Main - это только пример использования процедуры PivotDimensionByName
'Вызов PivotDimensionByName осуществляется со следующими параметрами:
' objPivot: 		ссылка на активированную мобильную таблицу
' strDimensionName: текст - имя размерности, подлежащей вращению (переносу в другое измерение)
' intFrom: 			где осуществлять поиск размерности
' intTo: 			куда перемещать найденную размерность
' intPosition: 		место в измерении, куда нужно вставить размерность
'можно использовать константы PVT_LayerDimension, PVT_RowDimension,
' PVT_ColumnDimension, PVT_AnyDimension для параметров intFrom и intTo;
' PVT_MoveDimensionFirst, PVT_MoveDimensionLast для параметра intPosition (описания констант см. ниже).

Sub Main
Dim objPivot As PivotTable, objItem As ISpssItem 
Dim intPos As Integer 

	'intPos = PVT_MoveDimensionFirst
	intPos = PVT_MoveDimensionLast
	'intPos = 1000 'недопустимое значение - будет проигнорировано

	'Следующая пара строк - просто чтобы получить ссылку на мобильную таблицу, с которой будем работать.
	GetFirstSelectedPivot objPivot, objItem, True, True
	If objPivot Is Nothing Then Exit Sub

	PivotDimensionByName objPivot, "Statistics", _
		PVT_AnyDimension, PVT_LayerDimension, intPos
	ForceItemUpdate objItem
	MsgBox "Осуществлён поворот в слои?", vbQuestion

	Set objPivot = objItem.ActivateTable
	PivotDimensionByName objPivot, "Statistics", _
		PVT_LayerDimension, PVT_RowDimension, intPos
	ForceItemUpdate objItem
	MsgBox "Осуществлён поворот в строки?", vbQuestion

	Set objPivot = objItem.ActivateTable
	PivotDimensionByName objPivot, "Statistics", _
		PVT_ColumnDimension, PVT_RowDimension, intPos
	ForceItemUpdate objItem
	MsgBox "Осуществлён поворот в строки?", vbQuestion

End Sub

'Не копируйте содержимое данной процедуры Sub Main в вашу собственную программу: это только пример!

'Вместо этого, добавьте в вашу программу следующие процедуры:
' PivotDimensionByName, 
' DoPivotDimension, 
' FindLayerDimension, 
' FindRowDimension, 
' FindColumnDimension, 
' ForceItemUpdate, 
' (и соответствующие константы)
' 

'-------------------------------------------------------- 
'НАЧАЛО кода определяющего и обслуживающего процедуру PivotDimensionByName
'-------------------------------------------------------- 
'КОНСТАНТЫ, используемые процедурой PivotDimensionByName
'---- Константы для параметров intFrom и intTo, участвующих в вызове PivotDimensionByName
' параметры могут принимать следующие значения:
Const PVT_LayerDimension As Integer = 0 'измерение слоёв
Const PVT_RowDimension As Integer = 1 'измерение строк
Const PVT_ColumnDimension As Integer = 2 'измерение столбцов
Const PVT_AnyDimension As Integer = 3 'любое измерение (все измерения)
'---- Константы для параметра intPosition
' Возможно одно из следующих двух значений,
' либо любое неотрицательное целое число, указывающее номер желаемой позиции:
Const PVT_MoveDimensionFirst As Integer = -1 'вставка первым элементом измерения
Const PVT_MoveDimensionLast As Integer = -2 'вставка последним элементом измерения
'-------------------------------------------------------- 
'Вызов процедуры PivotDimensionByName со следующими параметрами:
' objPivot: ссылка на активированную мобильную таблицу
' strDimensionName: строка с именем размерности, подвергаемой вращению
' intFrom: в каких измерениях ищем размерность
' intTo: куда будем переносить размерность
' intPosition: вставка размерности в нужное измерение перед размерностью с указанным номером
'-------------------------------------------------------- 
Sub PivotDimensionByName ( _
	objPivot As PivotTable, _
	strDimensionName As String, _
	intFrom As Integer, _
	intTo As Integer, _
	intPosition As Integer)

Dim objDim As ISpssDimension 
Dim objPivotMgr As ISpssPivotMgr
Dim i As Long
Dim intNumDim As Integer 

Set objPivotMgr = objPivot.PivotManager 
Select Case intFrom 
	Case PVT_LayerDimension
		Set objDim = FindLayerDimension(objPivotMgr, strDimensionName)
	Case PVT_RowDimension
		Set objDim = FindRowDimension(objPivotMgr, strDimensionName)
	Case PVT_ColumnDimension
		Set objDim = FindColumnDimension(objPivotMgr, strDimensionName)
	Case PVT_AnyDimension
		Set objDim = FindLayerDimension(objPivotMgr, strDimensionName)
		If objDim Is Nothing Then
			Set objDim = FindRowDimension(objPivotMgr, strDimensionName)
		End If
		If objDim Is Nothing Then
			Set objDim = FindColumnDimension(objPivotMgr, strDimensionName)
		End If
	Case Else
	'отлов ошибок в время отладки
	'If Err Then MsgBox Err.Description, vbExclamation, "Ошибка: " & Err
End Select

intNumDim = NumDimensions(objPivotMgr, intTo) 
Select Case intPosition 
	Case PVT_MoveDimensionFirst
		DoPivotDimension objDim, intTo, 0
	Case PVT_MoveDimensionLast
		DoPivotDimension objDim, intTo, intNumDim
	Case 0 To intNumDim
		If Not (objDim Is Nothing) Then
			DoPivotDimension objDim, intTo, intPosition
		End If
	Case Else
	'ничего не делаем
End Select
End Sub 

'-------------------------------------------------------- 
' процедура, обслуживающая PivotDimensionByName
'-------------------------------------------------------- 
Sub DoPivotDimension( _
objDim As ISpssDimension, _
intTo As Integer, intPosition As Integer)

Dim intNumDimensions As Integer 

If objDim Is Nothing Then Exit Sub 

On Error Resume Next 

	Select Case intTo
		Case PVT_LayerDimension
			objDim.MoveToLayer intPosition
		Case PVT_RowDimension
			objDim.MoveToRow intPosition
		Case PVT_ColumnDimension
			objDim.MoveToColumn intPosition
		Case Else
			Debug.Print "Неверный тип размерности!"
	End Select
'отлов ошибок во время отладки
'If Err Then MsgBox Err.Description, vbExclamation, "Ошибка: " & Err
End Sub 

'-------------------------------------------------------- 
' функция, обслуживающая PivotDimensionByName (поиск в измерении слоёв)
'-------------------------------------------------------- 
'возвращает ссылку на объект SPSS Dimension (найденную размерность)
'возвращает Nothing, если размерность с нужным именем не найдена
'-------------------------------------------------------- 
Function FindLayerDimension( _
objPivotMgr As ISpssPivotMgr, _
strDimensionName As String) As ISpssDimension

Dim objDim As ISpssDimension 
Dim i As Long 

With objPivotMgr 
	For i = .NumLayerDimensions - 1 To 0 Step -1
		Set objDim = .LayerDimension(i)
		If objDim.DimensionName = strDimensionName Then
			Exit For
		Else					' ### - добавлено перев.
			Set objDim=Nothing	' ### - добавлено перев.
		End If
	Next
End With
Set FindLayerDimension = objDim 
End Function 

'-------------------------------------------------------- 
' функция, обслуживающая PivotDimensionByName (поиск в измерении строк)
'-------------------------------------------------------- 
'возвращает ссылку на объект SPSS Dimension (найденную размерность)
'возвращает Nothing, если размерность с нужным именем не найдена
'-------------------------------------------------------- 
Function FindRowDimension( _
objPivotMgr As ISpssPivotMgr, _
strDimensionName As String) As ISpssDimension

Dim objDim As ISpssDimension 
Dim i As Long 

With objPivotMgr 
	For i = .NumRowDimensions - 1 To 0 Step -1
		Set objDim = .RowDimension(i)
		If objDim.DimensionName = strDimensionName Then
			Exit For
		Else					' ### - добавлено перев.
			Set objDim=Nothing	' ### - добавлено перев.
		End If
	Next
End With
Set FindRowDimension = objDim 
End Function 

'-------------------------------------------------------- 
' функция, обслуживающая PivotDimensionByName (поиск в измерении столбцов)
'-------------------------------------------------------- 
'возвращает ссылку на объект SPSS Dimension (найденную размерность)
'возвращает Nothing, если размерность с нужным именем не найдена
'-------------------------------------------------------- 
Function FindColumnDimension( _
objPivotMgr As ISpssPivotMgr, _
strDimensionName As String) As ISpssDimension

Dim objDim As ISpssDimension 
Dim i As Long 

With objPivotMgr 
	For i = .NumColumnDimensions - 1 To 0 Step -1
		Set objDim = .ColumnDimension(i)
		If objDim.DimensionName = strDimensionName Then
			Exit For
		Else					' ### - добавлено перев.
			Set objDim=Nothing	' ### - добавлено перев.
		End If
	Next
End With
Set FindColumnDimension = objDim 
End Function 

'-------------------------------------------------------- 
' функция, обслуживающая PivotDimensionByName
'-------------------------------------------------------- 
'возвращает число размерностей в измерении
'возвращает 0, если вызвана с неподходящими параметрами
'-------------------------------------------------------- 
Function NumDimensions( _
objPivotMgr As ISpssPivotMgr, _
intDimension As Integer) As Integer

Dim intNum As Integer 

On Error Resume Next 
	With objPivotMgr
		Select Case intDimension
		Case PVT_LayerDimension
			intNum = .NumLayerDimensions
		Case PVT_RowDimension
			intNum = .NumRowDimensions
		Case PVT_ColumnDimension
			intNum = .NumColumnDimensions
		Case Else
			'по умолчанию - 0
		End Select
	End With
	NumDimensions = intNum
End Function 

'-------------------------------------------------------- 
' процедура, обслуживающая PivotDimensionByName
'-------------------------------------------------------- 
' Вызов, если изменённая мобильная таблица отображается некорректно
' до перерисовки: обычно не требуется, но иногда бывает полезна.
'-------------------------------------------------------- 
Sub ForceItemUpdate(objItem As ISpssItem) 
	With objItem
	.Deactivate
	.Activate
	.Deactivate
	End With
End Sub

'-------------------------------------------------------- 
'КОНЕЦ кода, определяющего и обслуживающего процедуру
'--------------------------------------------------------