Как назначить максимальное количество строк для макроса автоматически?

Название моего вопроса может быть немного двусмысленным.

Ранее я хотел "получить полный список подкаталогов" и затем прочитать файлы из этих подкаталогов в Stata (см. Этот пост и этот пост).

Благодаря замечательному предложению @Roberto Ferrer, мне почти удается это сделать. Но тогда я столкнулся с другой проблемой. Поскольку у меня так много отдельных файлов, длина локального макроса, кажется, достигает верхней границы. После команды local n: word count Stata отправляет сообщение об ошибке:

Подстановка макросов приводит к слишком длинной строке.

Строка, полученная в результате замены макросов, будет длиннее, чем разрешено. Максимально допустимая длина составляет 645 216 символов, которая рассчитывается на основе установленного maxvar. Вы можете изменить это в Stata/SE и Stata/MP. То, что следует, уместно, только если вы используете Stata/SE или Stata/MP.

Максимальная длина строки определяется как 16 больше максимальной длины макроса, которая в настоящее время составляет 645 200 символов. Каждое увеличение единицы в установленном maxvar увеличивает максимумы длины на 129. Максимальное значение установленного maxvar составляет 32,767. Таким образом, максимальная длина строки может быть установлена ​​до 4 227 159 символов, если вы установите для maxvar наибольшее значение.

г (920);

Когда я уменьшаю количество subdirs до 5, Stata работает нормально. Имея примерно 100 дочерних папок, я предполагаю повторить действия 20 раз. Ну, это управляемо, но я все еще хочу знать, смогу ли я полностью автоматизировать этот процесс, более конкретно, чтобы "исчерпать" максимально допустимую длину макроса - импортировать файлы и добавить другую группу подкаталогов в следующий раз.

Ниже вы можете найти мой код:

//====================================
//=== read and clean projects data ===
//====================================
version 14
set linesize 80
set more off

clear
macro drop _all
set linesize 200
cd G:\Data_backup\Soufang_data


*----------------------------------
* Read all files within dictionary
*----------------------------------


* Import the first worksheets 1:"项目首页" 2:"项目概况" 3:"成交详情"
* worksheet1

filelist, directory("G:\Data_backup\Soufang_data") pattern(*.xlsx)

* Add pattern(*.xlsx) provent importing add file type( .doc or .dta)

gen tag = substr(reverse(dirname),1,6) == "esuoh/"
keep if tag==1
gen path = dirname+"\"+filename
qui valuesof path if tag==1
local filelist = r(values)

split dirname, parse("\" "/")
ren dirname4 citylist
drop dirname1-dirname3 dirname5
qui valuesof citylist if tag==1
local city = r(values)

local count = 1
local n:word count `filelist'

  forval i = 1/`n' {
      local file    : word `i' of `filelist'
      local cityname: word `i' of `city'

      ** don't add xlsx after `file', suffix has been added
      ** write "`file'" rather than `file', I don't know why but it works
      qui import excel using "`file'",clear
      cap qui sxpose,clear
      cap qui drop in 1/1
      gen city = "`cityname'"


      if `count'==1 {
          save house.dta,replace emptyok
         }
      else          {
          qui append using house
          qui save house.dta,replace emptyok
          }

      local ++count
      } 

Спасибо.

1 ответ

Решение

Вам не нужно хранить весь список файлов в макросе. filelist создает базу данных файлов, с которыми вы хотите работать. Просто сохраните его и перезагрузите для каждого файла, который вы хотите обработать. Вы также используете очень неэффективный способ добавления наборов данных. По мере роста добавляемого набора данных стоимость его перезагрузки и сохранения становится очень высокой и может замедлить весь процесс до сканирования.

Вот эскиз того, как обрабатывать ваши файлы Excel

filelist, directory(".") pattern(*.xlsx)
save "myfiles.dta", replace

local n = _N

forval i = 1/`n' {

    use in `i' using "myfiles.dta", clear

    local f = dirname + "/" + filename

    qui import excel using "`f'",clear

    tempfile res`i'
    save "`res`i''"

} 

clear
forval i = 1/`n' {

    append using "`res`i''"

} 

save "final.dta", replace
Другие вопросы по тегам