Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 198: iefielkit aux functions other commands #201

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4552dab
Created iefieldkit_aux.do
DenisseO Nov 11, 2021
c752413
iecodebook: use auxiliary functions to test files
DenisseO Nov 11, 2021
c69302b
ieduplicates: use auxiliary functions to test files
DenisseO Nov 11, 2021
8234e8d
ietestform: use auxiliary functions to test files
DenisseO Nov 11, 2021
553c0ae
iefieldkit_aux: Remove some conditions from ieaux_filename functions
DenisseO Nov 29, 2021
9cac6b2
iefieldkit_aux: Change ieaux_folderpath function syntaxis
DenisseO Nov 29, 2021
ce9021e
iefieldkit: Check that a filename was specified
DenisseO Nov 29, 2021
506a71e
iefieldkit_aux: Add ieaux_filename command in the others commands
DenisseO Nov 30, 2021
2d80a4b
iefieldkit_aux: Drop filename condition in ieaux_filename
DenisseO Dec 1, 2021
7279d5c
iefieldkit_aux: Test if there is a filename
DenisseO Dec 1, 2021
a5fe65a
iefieldkit_aux: minor change
DenisseO Dec 1, 2021
ad01494
iefieldkit_aux: Add minor description
DenisseO Dec 1, 2021
68605b2
iefieldkit_aux: Update ieaux_fileext
DenisseO Dec 7, 2021
39766c3
ieduplicates: Update iefieldkit_aux commands
DenisseO Dec 7, 2021
12c57c8
iefieldkit_aux: Change to ieutil_ commands names
DenisseO Dec 7, 2021
3dd13a6
iefieldkit_aux: Minor change
DenisseO Dec 7, 2021
c19f47c
iefieldkit_aux: Minor change
DenisseO Dec 9, 2021
1c04e1f
iecodebook: update ieutil_ commands
DenisseO Dec 10, 2021
5477722
ieduplicates: update ieutil_ commands
DenisseO Dec 10, 2021
ec97a38
ietestform: update ieutil_ commands
DenisseO Dec 10, 2021
15cbd1b
Merge branch 'main' into issue-198-other-commands
luizaandrade Feb 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 13 additions & 32 deletions src/ado_files/iecodebook.ado
Original file line number Diff line number Diff line change
Expand Up @@ -28,39 +28,20 @@ cap program drop iecodebook
// Select subcommand
noi di " "
gettoken subcommand anything : anything

// Get the foldername, filename and the file extension
ieaux_filename using `using'

// Check folder exists

// Start by standardize all slashes to forward slashes, and get the position of the last slash
local using = subinstr("`using'","\","/",.)
local r_lastslash = strlen(`"`using'"') - strpos(strreverse(`"`using'"'),"/")
if strpos(strreverse(`"`using'"'),"/") == 0 local r_lastslash -1 // Set to -1 if there is no slash

// Get the full folder path and the file name
local r_folder = substr(`"`using'"',1,`r_lastslash')
local r_file = substr(`"`using'"',`r_lastslash'+2,.)

// Test that the folder for the report file exists
mata : st_numscalar("r(dirExist)", direxists("`r_folder'"))
if `r(dirExist)' == 0 {
noi di as error `"{phang}The folder [`r_folder'/] does not exist.{p_end}"'
error 601
}

// Find the position of the last dot in the file name and get the file format extension
local r_lastsdot = strlen(`"`r_file'"') - strpos(strreverse(`"`r_file'"'),".")
local r_fileextension = substr(`"`r_file'"',`r_lastsdot'+1,.)

// If no fileextension was used, then add .xslx to "`using'"
if "`r_fileextension'" == "" {
local using "`using'.xlsx"
}
// Throw an error if user input uses any extension other than the allowed
else if !inlist("`r_fileextension'",".xlsx",".xls") & !regexm(`"`options'"',"tempfile") {
di as error "The codebook may only have the file extension [.xslx] or [.xls]. The format [`r_fileextension'] is not allowed."
error 601
}

//Standarize path
local using "`r(using)'"

// Test that the folder exists
ieaux_folderpath, folderpath("`r(folder)'")


// Test the form file: xls or xlsx
ieaux_fileext using `using', fileext(xlsx xls) testfileext("`r(fileext)'")
local using "`r(using)'"

// Throw error on [template] if codebook cannot be created
if inlist("`subcommand'","template","export") & !regexm(`"`options'"',"replace") & !regexm(`"`options'"',"verify") {
Expand Down
89 changes: 19 additions & 70 deletions src/ado_files/ieduplicates.ado
Original file line number Diff line number Diff line change
Expand Up @@ -919,68 +919,28 @@ cap program drop testpath
Prepare file name if option using was specified
*******************************************************************************/

* Parse using option to get (1) the folder path (2) the name of the report and
* (3) the format selected
else if "`using'" != "" {

* Replace any backslashes with forward slashes so it's compatible with
* different OS and so we know what to look for as separators when parsing
local using = subinstr("`using'", "\", "/", .)

* Separate the folder name from the file name
strlast, expression("`using'") character("/")

* If a folder was specified, get the folder path
if `r(lastpos)' > 0 {
local folder = substr("`using'", 1, `r(lastpos)')
}
else {
*get the folder path, the name of the report and, the format selected
ieaux_filename using `using'
local folder `r(folder)'/
local name `r(filename)'
local ext `r(fileext)'

* Standarize path
local using "`r(using)'"

* Check if the folder exist
if missing("`folder'") {
noi di as error "{phang}You have not specified a folder path to the duplicates report. An absolute folder path is required.{p_end}"
noi di as error `"{phang}This command will not work if you are trying to use {inp:cd} to set the directory and open or save files. To know more about why this practice is not allowed, {browse "https://dimewiki.worldbank.org/wiki/Stata_Coding_Practices#File_paths":see this article in the DIME Wiki}.{p_end}"'
noi di as error ""
error 198
exit
}

* Everything that comas after the folder path is the file name and format
local file = substr("`using'", `r(lastpos)' + 1, .)

* If a filename was specified, separate the file name from the file format
if "`file'" != "" {

* Get index of separation between file name and file format
strlast, expression("`file'") character(".")

* If a format was specified, separate name and format
if `r(lastpos)' > 0 {
local ext = substr("`file'", `r(lastpos)', .) // File format starts at the last period and ends at the end of the string
local name = substr("`file'", 1, `r(lastpos)' - 1) // File name starts at the beginning and ends at the last period
}
* If a format was not specified, the name is everything that follows the
* folder path
else {
local name `file'
}
}
* Check that a folder name was specified and through an error if it wasn't
if ("`file'" == "" | ( "`file'" != "" & "`name'" == "")) {
noi di as error "{phang}`using' not a valid filename.{p_end}"
noi di ""
error 198
exit
}

* The default format is xlsx. Other possible formats are xls
if "`ext'" == "" {
local ext .xlsx
}
else if !inlist("`ext'", ".xls", ".xlsx") {
noi di ""
noi di as error `"{phang}`ext' is not currently supported as a format for the duplicates report. Supported formats are: xls, xslx. If you have a suggestion of a different format to support, please e-mail [email protected] or {browse "https://github.com/worldbank/iefieldkit/issues":create an issue on the iefieldkit GitHub repository.}{p_end}"'
noi di ""
error 198 //TODO: check error code
exit
}

* Check if the file extension is the correct.
ieaux_fileext using `using', fileext(xlsx xls) testfileext(`ext')
local using "`r(using)'"

}

* Create file name if using was not specified
Expand All @@ -991,24 +951,13 @@ cap program drop testpath
if "`suffix'" != "" local name `name'_`suffix'
local ext .xlsx
}

* Test that the folder indicated existes
mata : st_numscalar("r(dirExist)", direxists("`folder'"))

** If the folder does not exist, throw an error
if `r(dirExist)' == 0 {

*Variable exist, output error
noi di as error "{phang}The folder specified does not exist :`folder'.{p_end}"
noi di ""
error 198 // TODO: check error code
exit
}

* Test that the folder exists
ieaux_folderpath, folderpath("`folder'")

return local name `name'
return local ext `ext'
return local folder `folder'

end

/*******************************************************************************
Expand Down
110 changes: 110 additions & 0 deletions src/ado_files/iefieldkit_aux.do
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
This do-file contains functions to perform the following tasks:
*/

/*******************************************************************************
GET FILE COMPONENTS
- Folder path
- File extension and file name
********************************************************************************/
cap program drop ieaux_filename
program ieaux_filename, rclass
DenisseO marked this conversation as resolved.
Show resolved Hide resolved

syntax using/

* Standardize file path so Mac and Linux systems handle this path correctly
local using = subinstr("`using'", "\", "/", .)

* Separate the folder name from the file name
local r_lastslash = strlen(`"`using'"') - strpos(strreverse(`"`using'"'),"/")
if strpos(strreverse(`"`using'"'),"/") == 0 local r_lastslash -1 // Set to -1 if there is no slash

* If a folder was specified, get the folder path
local folder = substr(`"`using'"',1,`r_lastslash')

* Everything that comes after the folder path is the file name and format
local file = substr("`using'", `r_lastslash' + 2, .)

* If a filename was specified, separate the file name from the file format
if "`file'" != "" {
Copy link
Contributor

@kbjarkefur kbjarkefur Nov 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When would this be empty? using/ is required and folders are defined as anything before a /. So if / exists then folders are anything before / and file is whatever is after and if there is no / then file is the same as using/? Right? Or is there any input for which this command stores somethin in folder but file is empty?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe if using/ is folderA/folderB/. But then the input is no longer a filename and it is a path. I think that that should either be an error or the command should be called ieaux_parse_filepath and then a path without a filename should be just as valid input as a filename with or without path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if there is no / then file is the same as using/

Copy link
Contributor Author

@DenisseO DenisseO Dec 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, the best option is to change the name to ieaux_parse_filepath.
I made some changes for this to be a valid imput.
2d80a4b
7279d5c


* Get index of separation between file name and file format
local r_lastsdot = strlen(`"`file'"') - strpos(strreverse( `"`file'"'),".")

local fileext = substr(`"`file'"',`r_lastsdot'+1,.) // File format starts at the last period and ends at the end of the
if "`fileext'" == "" local fileext 1

local filename = substr("`file'", 1, `r_lastsdot') // File name starts at the beginning and ends at the last period

}

return local folder `folder'
return local file `file'
return local filename `filename'
return local fileext `fileext'
return local using `using'
end


/*******************************************************************************
TEST IF A FOLDER ALREADY EXISTS
- option "folderpath" is the path to the directory
- option "description" will be used in the error message to explain where this folder path was referenced

********************************************************************************/
cap program drop ieaux_folderpath
program ieaux_folderpath

syntax using/, [description(string)]
ieaux_filename using `using'

* Test that the folder for the report file exists
if !missing("`r(folder)'"){
mata : st_numscalar("r(dirExist)", direxists("`r(folder)'"))
if `r(dirExist)' == 0 {
noi di as error `"{phang}The folder path [`r(folder)'/] used `description' does not exist.{p_end}"'
error 601
}
}

end


/*******************************************************************************
TEST IF THE FILE EXTENSION IS THE CORRECT
- option "testfileext" is a namelist of the correct extensions that the file may only have

********************************************************************************/

cap program drop ieaux_fileext
program ieaux_fileext, rclass

syntax using/, testfileext(string)
ieaux_filename using `using'

if !missing("`r(file)'") {
* Check if the file extension is the correct
local ext ""
foreach value in `testfileext' {
if (".`value'" == "`r(fileext)'") local errorfile 1
local ext `".`value' `ext'"'
}

local wcount = `: word count `testfileext''
if ("`errorfile'" != "1") & ("`r(fileext)'" != "1") {
if `wcount' > 1 local pluralms= "s"
noi di as error `"{phang}The file {bf:`using'} may only have the extension format`pluralms' [`ext']. The format [`r(fileext)'] is not allowed.{p_end}"'
error 198
}

* If no file extension was used, then add the extension
if "`r(fileext)'" == "1" {
local ext = word("`testfileext'",1) // If there are more than one extension, get first
local using "`using'.`ext'"
}
}
return local using `using'
Copy link
Contributor

@kbjarkefur kbjarkefur Dec 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
syntax using/, testfileext(string)
ieaux_filename using `using'
if !missing("`r(file)'") {
* Check if the file extension is the correct
local ext ""
foreach value in `testfileext' {
if (".`value'" == "`r(fileext)'") local errorfile 1
local ext `".`value' `ext'"'
}
local wcount = `: word count `testfileext''
if ("`errorfile'" != "1") & ("`r(fileext)'" != "1") {
if `wcount' > 1 local pluralms= "s"
noi di as error `"{phang}The file {bf:`using'} may only have the extension format`pluralms' [`ext']. The format [`r(fileext)'] is not allowed.{p_end}"'
error 198
}
* If no file extension was used, then add the extension
if "`r(fileext)'" == "1" {
local ext = word("`testfileext'",1) // If there are more than one extension, get first
local using "`using'.`ext'"
}
}
return local using `using'
syntax using/, allowed_exts(string) [default_ext(string)]
*Parse the unput
ieaux_filename using `using'
local this_file "`r(file)'"
local this_ext = subinstr("`r(file)'",".","")
*Test if using has no file
if missing("`this_file'") {
noi di as error `"{phang}The path {bf:`using'} does not have a file name for which extension can be tested.{p_end}"'
error 198
}
*Test is using has no file extension
else if missing("`this_ext'") {
*Test if no deafult ext was provided
if missing("`default_ext'") {
noi di as error `"{phang}The file in {bf:`using'} does not have a file extension and no default was provided.{p_end}"'
error 198
}
*Apply the deafult extension
else {
local return_file "`using'.`default_ext'"
}
}
* Using has both file and extension
else {
* Test if extension is among the allowed extensions
if `: list this_ext in allowed_exts' == 1 {
*Extension is allowed, return file name as is
local return_file "`using'"
}
* File extension used is not allowed
else {
noi di as error `"{phang}The file extension [`this_ext'] in file {bf:`using'} is not allowed. Allowed extensions: [`allowed_exts'].{p_end}"'
error 198
}
}
*Return checked filename
return local filename "`return_file'"

I would approach this command like this

end



73 changes: 23 additions & 50 deletions src/ado_files/ietestform.ado
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
capture program drop ietestform
program ietestform , rclass

qui {

qui{
version 13

preserve
Expand All @@ -30,15 +29,20 @@ qui {
}
local surveyform `"`using'`surveyform'"'

*Get the foldername, filename and the file extension for the survey file input
ieaux_filename using `surveyform'

* Test for form file is xls or xlsx
local surveyformtype = substr(`"`surveyform'"',strlen(`"`surveyform'"')-strpos(strreverse(`"`surveyform'"'),".")+1,.)
if !(`"`surveyformtype'"' == ".xls" | `"`surveyformtype'"' == ".xlsx") {
noi di as error `"{phang}The survey form file [`surveyform'] must have file extension .xls or .xlsx specified in the option.{p_end}"'
error 601
}
* Standarize path
local surveyform "`r(using)'"

*Test that the folder exists
ieaux_folderpath, folderpath("`r(folder)'") description("in surveyform ")

* Test if the form file is xls or xlsx
ieaux_fileext using `surveyform', fileext(xlsx xls) testfileext("`r(fileext)'")
local surveyform "`r(using)'"

*Test that the form file exists
*Test if the form file exists
cap confirm file "`surveyform'"
if _rc {

Expand All @@ -51,49 +55,18 @@ qui {
*********/

*********
*Get the folder for the report file

**Start by finding the position of the last forward slash. If no forward
* slash exist, it is zero, then replace to to string len so it is never
* the min() below.
local r_f_slash = strpos(strreverse(`"`reportsave'"'),"\")
if `r_f_slash' == 0 local r_f_slash = strlen(`"`reportsave'"')

**Start by finding the position of the last backward slash. If no backward
* slash exist, it is zero, then replace to to string len so it is never
* the min() below.
local r_b_slash = strpos(strreverse(`"`reportsave'"'),"/")
if `r_b_slash' == 0 local r_b_slash = strlen(`"`reportsave'"')

*Get the last slash in the report file path regardless of back or forward
local r_lastslash = strlen(`"`reportsave'"')-min(`r_f_slash',`r_b_slash')

*Get the folder
local r_folder = substr(`"`reportsave'"',1,`r_lastslash')
*Get the foldername, filename and the file extension for the report file
ieaux_filename using `using'

* Standarize path
local using "`r(using)'"

*Test that the folder for the report file exists
mata : st_numscalar("r(dirExist)", direxists("`r_folder'"))
if `r(dirExist)' == 0 {
noi di as error `"{phang}The folder used in [`reportsave'] does not exist.{p_end}"'
error 601
}

*Get the filename and the file extension type from the report file
local r_filename = substr(`"`reportsave'"',`r_lastslash'+1, .)
local r_filenametype = substr(`"`r_filename'"',strlen(`"`r_filename'"')-strpos(strreverse(`"`r_filename'"'),".")+1,.)
*Test what the file extension type is
if (`"`r_filenametype'"' == "") {
*No file type specified, add .csv
local reportsave `"`reportsave'.csv"'
}
else if (`"`r_filenametype'"' != ".csv") {
*Incorrect file type added. Throw error
noi di as error `"{phang}The report file [`reportsave'] may only have the file extension .csv.{p_end}"'
error 601
}
else {
* All is correct, do nothing
}
ieaux_folderpath, folderpath("`r(folder)'") description("in [`reportsave'] ")

*Test if the file extension type from the report file is csv
ieaux_fileext `using', fileext(csv) testfileext(`r_fileext')
local using "`r(using)'"

*Tempfile that will be used to write the report
tempfile report_tempfile
Expand Down