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 all 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
49 changes: 13 additions & 36 deletions src/ado_files/iecodebook.ado
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

cap program drop iecodebook
program def iecodebook

qui do "${GitHub}\iefieldkit\src\ado_files/iefieldkit_aux.do"

version 13 // Requires 13.0 due to use of long macros

Expand All @@ -29,49 +31,24 @@ cap program drop iecodebook
// Select subcommand
noi di " "
gettoken subcommand anything : anything

// 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
}



// Test that the folder exists
ieutil_folderpath using `using', description("in the file")


// Test the form file: xls or xlsx
ieutil_fileext using `using', allowed_exts(.xlsx .xls) default_ext(.xlsx)
local using "`r(file_path)'"


// Throw error on [template] if codebook cannot be created
if inlist("`subcommand'","template","export") & !regexm(`"`options'"',"replace") & !regexm(`"`options'"',"verify") {

cap confirm file "`using'"
if (_rc == 0) & (!strpos(`"`options'"',"replace")) {
di as err "That codebook already exists. {bf:iecodebook} will only overwrite it if you specify the [replace] option."
error 602
}

cap confirm new file "`using'"
if (_rc != 0) & (!strpos(`"`options'"',"replace")) {
di as error "{bf:iecodebook} could not create file `using'. Check that the file path is correctly specified."
Expand Down
103 changes: 27 additions & 76 deletions src/ado_files/ieduplicates.ado
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
program ieduplicates , rclass


qui {
qui {

syntax varname [using/] , UNIQUEvars(varlist) ///
[force ///
Expand All @@ -17,7 +17,9 @@
duplistid(string) datelisted(string) datefixed(string) correct(string) drop(string) newid(string) initials(string) notes(string) listofdiffs(string)]

version 11.0


qui do "${GitHub}\iefieldkit\src\ado_files/iefieldkit_aux.do"

*Add version of Stata fix
//Make sure that keepvars are still saved if saved if the duplicates file
* is generated on a subset of the data. For example, duplicates from
Expand All @@ -30,7 +32,6 @@
* message to this that is more informative.

preserve

/***********************************************************************
************************************************************************
Section 1 - Set up locals needed in data
Expand Down Expand Up @@ -867,7 +868,7 @@
* the orignal data set in case of error.
use `dataToReturn', clear

}
}
end


Expand Down Expand Up @@ -932,68 +933,31 @@ 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 {

* Check if the folder exist
ieutil_parse_filepath using `using'
local folder `r(folderpath)'
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.
ieutil_fileext using `using', allowed_exts(.xlsx .xls) default_ext(.xlsx)
local using "`r(file_path)'"

* Test that the folder exists
ieutil_folderpath using `using'

* Get the folder path, the name of the report and, the format selected
ieutil_parse_filepath using `using'
local folder `r(folderpath)'/
local name `r(filename)'
local ext `r(fileext)'

}

* Create file name if using was not specified
Expand All @@ -1004,24 +968,11 @@ 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
}


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

return local folder `folder'
end

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

/*******************************************************************************
GET FILE COMPONENTS
- Folder path
- File extension and file name
********************************************************************************/
cap program drop ieutil_parse_filepath
program ieutil_parse_filepath, rclass

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

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

}

return local folderpath `folder'
return local file `file'
return local filename `filename'
return local fileext `fileext'
return local filepath `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 ieutil_folderpath
program ieutil_folderpath

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

* Test that the folder for the report file exists
if !missing("`r(folderpath)'"){
mata : st_numscalar("r(dirExist)", direxists("`r(folderpath)'"))
if `r(dirExist)' == 0 {
noi di as error `"{phang}The folder path [`r(folderpath)'/] 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 ieutil_fileext
program ieutil_fileext, rclass

syntax using/, allowed_exts(string) [default_ext(string)]

*Parse the input
ieutil_parse_filepath using `using'
local this_filename "`r(filename)'"
local this_ext "`r(fileext)'"

*Test if using has no file
if missing("`this_filename'") {
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 file_path `return_file'
end



Loading