-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbloomimport.ado
412 lines (373 loc) · 11.8 KB
/
bloomimport.ado
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
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
*! version 1.5.3 Nicola Tommasi 02feb2025
* -xframeappend replaced by fframeappend (please use version >= 1.1.2)
*! version 1.5.2 Nicola Tommasi 30jan2025
* -check missings package installation
* -bugs fix in export(long) (variable names)
*! version 1.5.1 Nicola Tommasi 01oct2024
* -bugs fix
*! version 1.5 Nicola Tommasi 14sep2024
* -dates(single|multi)
* -minor changes
*! version 1.4 Nicola Tommasi 09mar2024
* -export(wide|long)
*! version 1.2 Nicola Tommasi 09mar2024
* -datastart() optional. If not specified, datastart=cellrange+1
*! version 1.1 Nicola Tommasi 07mar2023
* -prevent xframeappend error "shared variables in frames being combined must be both numeric or both string"
*! version 1.0b Nicola Tommasi 29nov2022
* -version 17 use frames, 15 & 16 tempfile
*! version 0.5 Nicola Tommasi 17nov2022
program bloomimport
**version 15
set tracedepth 1
**only if version >= 17
**which name_ado_file
syntax using/, sheet(string) cellrange(string) [export(string) nvar(integer 0) lasttick(string) /*datastart(string)*/ from(string) to(string) dates(string) debug ]
tempname temp fr_fusion ABS ABE
tempfile buildingDB
capture frames reset `temp'
capture frames reset `fr_fusion'
local version `c(stata_version)'
capture which missings
if _rc==111 {
di in yellow "missings not installed.... installing..."
ssc inst missings
di in yellow "missings has been correctly installed!"
}
if `version'>=17 {
capture which fframeappend
if _rc==111 {
di in yellow "fframeappend not installed.... installing..."
ssc inst fframeappend
di in yellow "fframeappend has been correctly installed!"
}
}
if "`export'"=="" local export wide
if "`dates'"=="" local dates single /*multi*/
if "`dates'" != "single" & "`dates'" != "multi" {
di "dates() must be single or mutli"
exit
}
if "`export'"=="wide" {
qui import excel using "`using'", sheet("`sheet'") cellrange(`cellrange') clear allstring
if regexm("`cellrange'","(^[A-Z]*)") local firstrow = regexs(1)
mata: `ABS' = "`firstrow'"
mata: st_numscalar("datastartN", numofbase26(`ABS'))
if "`dates'" == "single" local datastartN = datastartN+1
else local datastartN = datastartN
if regexm("`lasttick'","(^[A-Z]*)") local lasttickS= regexs(1)
mata: `ABE' = "`lasttickS'"
mata: st_numscalar("lasttickmata", numofbase26(`ABE'))
local lasttickmata = lasttickmata
local sta = `datastartN' /*colonna da cui partono i dati per dates(single), servono per mata */
local STA=`sta'
local LAST = `lasttickmata' /* è la colonna dove iniziano i dati dell'ultimo ticker --> numofbase26() */
if "`dates'" == "single" {
while `STA'<= `LAST' {
local END = `STA' + `nvar' - 1
mata: st_local("cellname", numtobase26(`STA'))
mata: st_local("cellfine", numtobase26(`STA'+`nvar'-1))
local Vname = `cellname' in 1
preserve
keep `firstrow' `cellname'-`cellfine'
local VtoDESTR = ""
forvalues c=`STA'/`END' {
mata: st_local("clnm", numtobase26(`c'))
local token =`clnm' in 2
capture confirm variable `token'
if _rc rename `clnm' `token'
else {
local token `token'2
rename `clnm' `token'
}
qui replace `token'="" if strmatch(`token',"*N/A*")
local VtoDESTR "`VtoDESTR' `token'"
}
qui gen ticker="`Vname'"
qui drop in 1/2
rename `firstrow' date
if `version'>=17 {
if `STA'==`sta' qui frame copy default `fr_fusion', replace
else {
qui frame copy default `temp'
if "`debug'"!=""{
di "temp"
summ
desc
fre ticker
}
frame change `fr_fusion'
if "`debug'"!=""{
di "fr_fusion"
desc
summ
}
**xframeappend `temp', drop fast
fframeappend, using(`temp') drop force
frame change default
}
}
else {
if `STA'==`sta' qui save `buildingDB', replace
else {
qui append using `buildingDB', force
qui save `buildingDB', replace
}
}
restore
if `STA'<=`LAST' local STA = `STA' + `nvar'
}
}
else { /*dates=multi*/
**set trace on
local STAi = `STA'
while `STAi'<= `LAST' {
local ENDi = `STAi' + `nvar'
mata: st_local("cellname", numtobase26(`STAi'))
mata: st_local("cellfine", numtobase26(`ENDi'))
local Vname = `cellname' in 1
preserve
keep `cellname'-`cellfine'
local VtoDESTR = ""
forvalues c=`STAi'/`ENDi' {
mata: st_local("clnm", numtobase26(`c'))
if `c'==`STAi' local token date
else local token = `clnm' in 2
capture confirm variable `token'
if _rc rename `clnm' `token'
else {
local token `token'2
rename `clnm' `token'
}
qui replace `token'="" if strmatch(`token',"*N/A*")
local VtoDESTR "`VtoDESTR' `token'"
}
qui gen ticker="`Vname'"
qui drop in 1/2
**qui destring `VtoDESTR', replace
qui drop if date==""
if `version'>=17 {
if `STAi'==`sta' qui frame copy default `fr_fusion', replace
else {
qui frame copy default `temp'
if "`debug'"!=""{
di "temp"
summ
desc
fre ticker
}
frame change `fr_fusion'
if "`debug'"!=""{
di "fr_fusion"
desc
summ
}
**xframeappend `temp', drop fast
fframeappend, using(`temp') drop force
frame change default
}
}
else {
if `STAi'==`sta' qui save `buildingDB', replace
else {
qui append using `buildingDB', force
qui save `buildingDB', replace
}
}
restore
if `STAi'<=`LAST' local STAi = `ENDi' + 2 /*empy col */
}
}
if `version'>=17 {
frame change `fr_fusion'
frame copy `fr_fusion' default, replace
frame change default
qui destring, replace
}
else {
use `buildingDB', clear
qui destring, replace
}
order ticker date
}
else { /*"`export'"=="long"*/
if "`dates'" == "single" {
qui import excel using "`using'", sheet("`sheet'") cellrange(`cellrange') clear allstring firstrow case(upper)
qui missings dropvars, force
if regexm("`cellrange'","(^[A-Z]*)") local firstrow = regexs(1)
rename `firstrow' ticker
label var ticker "Ticker"
qui carryforward ticker, replace
rename DATES field
label var field "Field"
qui ds, not(varl Ticker Field)
foreach V of varlist `r(varlist)' {
local vdesc : variable label `V'
local date = subinstr("`vdesc'","/","_",.)
local date = subinstr("`date'"," ","",.)
rename `V' _`date'
qui replace _`date'="" if strmatch(_`date',"#*")
}
if `version'>=18 {
qui reshape long _@, i(ticker field) j(date) favor(speed) string
qui reshape wide _, i(ticker date) j(field) string favor(speed)
}
else {
qui reshape long _@, i(ticker field) j(date) string
qui reshape wide _, i(ticker date) j(field) string
}
foreach V of varlist _* {
qui destring `V', replace
}
rename _* *
}
else { /*"`dates'" == "multi"*/
qui import excel using "`using'", sheet("`sheet'") cellrange(`cellrange') clear allstring case(upper)
if regexm("`cellrange'","(^[A-Z]*)") local firstrow = regexs(1)
rename `firstrow' ticker
label var ticker "Ticker"
qui carryforward ticker, replace
qui ds
local field = word("`r(varlist)'",2)
rename `field' field
label var field "Field"
qui drop if field==""
local tag = field in 1
tempname ticker_id field_id id fieldlen
qui gen `id'=_n
qui egen `ticker_id' = seq() if field=="`tag'"
qui carryforward `ticker_id', replace
qui bysort `ticker_id' (`id'): gen `field_id'=_n
label var `id' "tempvar"
label var `ticker_id' "tempvar"
label var `field_id' "tempvar"
qui levelsof `ticker_id', local(ticker_list)
foreach t of local ticker_list {
preserve
qui keep if `ticker_id'==`t'
qui missings dropvars, force
qui ds, not(varl Ticker Field tempvar)
foreach V of varlist `r(varlist)' {
local vname = `V' in 1
local vname = strtrim("`vname'")
local vname = subinstr("`vname'","/","",.)
rename `V' D`vname'
}
qui drop in 1
qui reshape long D@, i(ticker field) j(date) string
qui replace D="" if strmatch(D,"*N/A*")
qui gen `fieldlen'=strlen(field)
qui summ `fieldlen'
if `r(max)'>=32 local flag=1
else local flag=0
if `flag'==1 {
qui levelsof field if `fieldlen'>=32, local(lista)
local cnt=1
foreach F of local lista {
qui replace field = "tmp`cnt'" if field=="`F'"
local name`cnt' `F'
local cnt `++cnt'
}
}
capture drop `id' `field_id' `fieldlen'
qui reshape wide D, i(ticker date) j(field) string
if `flag'==1 {
local cnt `--cnt'
forvalues i=1/`cnt' {
rename Dtmp`i' `name`i''
label var `name`i'' "`name`i''" /*previene rename vars che iniziano con D nel ciclo sotto*/
}
}
foreach V of varlist D* {
local VNAME : variable label `V'
local VNAME : word 1 of `VNAME'
qui rename `V' `VNAME'
}
if `version'>=17 {
if `ticker_id'==1 qui frame copy default `fr_fusion', replace
else {
qui frame copy default `temp'
if "`debug'"!=""{
di "temp"
summ
desc
fre ticker
}
frame change `fr_fusion'
if "`debug'"!=""{
di "fr_fusion"
desc
summ
}
**xframeappend `temp', drop fast
fframeappend, using(`temp') drop force
frame change default
}
}
else {
if `ticker_id'==1 qui save `buildingDB', replace
else {
qui append using `buildingDB', force
qui save `buildingDB', replace
}
}
restore
}
**to avoid dates destring
if `version'>=17 {
frame change `fr_fusion'
frame copy `fr_fusion' default, replace
frame change default
qui ds
local VARLIST = "`r(varlist)'"
local VARLIST = subinstr("`VARLIST'"," date ", " ",1)
qui destring `VARLIST', replace
}
else {
use `buildingDB', clear
qui ds
local VARLIST = "`r(varlist)'"
local VARLIST = subinstr("`VARLIST'"," date ", " ",1)
qui destring `VARLIST', replace
}
}
}
end
/****
William Matsuoka
Putexcel Part II: numofbase26()
http://www.wmatsuoka.com/stata/putexcel-part-ii-numofbase26
****/
mata
real matrix numofbase26(string matrix base)
{
real matrix output, pwr, b
real scalar i, j, k, l
base = strupper(base)
output = J(rows(base), cols(base), .)
for (i=1; i<=rows(base); i++) {
for (j=1; j<=cols(base); j++) {
if (strlen(base[i,j]) == 1) output[i,j] = ascii(base[i,j]) - 64
else {
l = strlen(base[i,j])
b = pwr = J(1, l, .)
for (k=1; k<=l; k++) {
b[1,k] = ascii(substr(base[i,j], k, 1)) - 64
pwr[1, k] = l - k
}
output[i,j] = rowsum(b :* (26:^pwr))
}
}
}
return(output)
}
end
/***********
numtobase26() is an undocumented Mata function
that converts column numbers to Excel's column letters. For example, if
you want to know what the 27th column will be called in Excel you can
type in Stata:
. mata : numtobase26(27)
AA
*********/
exit