Note: I have a workaround, so this is only an attempt to understand the error.
Summary: I get a syntax error (failed to write table) when using putpdf
. The error seems to be connected to using the bold
option, but disappears when this option is replaced or erased.
I am trying to write a pdf with a series of tables using putpdf
. This is a new built-in command (Stata 15 only), so I can't tell if what I am experiencing is a bug or a problem with the way I have formatted things. Unfortunately, this issue is impossible to replicate without the data I am using: The same general idea using sysuse auto
couldn't replicate, so this is a weird one.
Start by adding in the data (this is from an ongoing survey I am checking daily, so I have trimmed it down to the parts that are replicating an error and replaced names with dummy names):
clear
cd [DIRECTORY] // Change this to yours
input str70 label str6 district str11 ta str23 village str27 cluster float(sdate coupons) byte shopid str33 reason
"Amosi - 1000001 - First Last (MARK-01-001)" "Mwan" "Kand" "Amosi" "First Last 22" 21266 . 13 "Not Yet Replaced"
"Amosi - 1000002 - First Last (MARK-01-001)" "Mwan" "Kand" "Amosi" "First Last 22" 21266 . 13 "Not Yet Replaced"
"Bello - 1000003 - First Last (MARK-01-001)" "Neno" "Damb" "Bello" "First Last 2" 21266 1 11 "Not Yet Replaced"
"Bello - 1000004 - First Last (MARK-01-001)" "Neno" "Chek" "Bello" "First Last 5" 21266 . 11 "Not Yet Replaced"
"Bello - 1000005 - First Last (MARK-01-001)" "Neno" "Damb" "Bello" "First Last 24" 21266 . 11 "Not Yet Replaced"
"Benalita - 1000006 - First Last (MARK-01-001)" "Neno" "Damb" "Benalita" "First Last 7" 21260 1 12 "Not Yet Replaced"
"Chakhumbira - 1000007 - First Last (MARK-01-001)" "Neno" "Damb" "Chakhumbira" "First Last 28" 21269 . 8 "Not Yet Replaced"
"Chapita - 1000008 - First Last (MARK-01-001)" "Neno" "Mlau" "Chapita" "First Last 32" . 1 1 ""
"Chapita - 1000009 - First Last (MARK-01-001)" "Neno" "Mlau" "Chapita" "First Last 3" . . 1 ""
"Chapita - 1000010 - First Last (MARK-01-001)" "Neno" "Mlau" "Chapita" "First Last 20" 21266 . 1 "Not Yet Replaced"
"Chapita - 1000011 - First Last (MARK-01-001)" "Neno" "Mlau" "Chapita" "First Last 9" . 1 1 ""
"Chapita - 1000012 - First Last (MARK-01-001)" "Neno" "Mlau" "Chapita" "First Last 31" 21262 . 1 "Not Yet Replaced"
"Chasesa - 1000013 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 16" . . 20 ""
"Chasesa - 1000014 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 30" 21263 1 3 "Not Yet Replaced"
"Chasesa - 1000015 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 16" . . 20 ""
"Chasesa - 1000016 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 25" . 1 20 ""
"Chasesa - 1000017 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 21" . . 20 ""
"Chasesa - 1000018 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 14" . . 20 ""
"Chasesa - 1000019 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 29" 21266 . 20 "Not Yet Replaced"
"Chasesa - 1000020 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 30" . . 3 ""
"Chasesa - 1000021 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 14" . . 20 ""
"Chasesa - 1000022 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 12" . 1 20 ""
"Chasesa - 1000023 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 26" 21251 . 1 "Not Yet Replaced"
"Chasesa - 1000024 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 21" 21249 . 20 "Not Yet Replaced"
"Chasesa - 1000025 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 27" 21250 . 20 "Not Yet Replaced"
"Chasesa - 1000026 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 11" 21249 . 20 "Not Yet Replaced"
"Chasesa - 1000027 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 26" . . 1 ""
"Chasesa - 1000028 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 4" . 1 20 ""
"Chasesa - 1000029 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 19" 21262 . 20 "Not Yet Replaced"
"Chasesa - 1000030 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 18" 21250 1 20 "Not Yet Replaced"
"Chasesa - 1000031 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 26" 21251 1 1 "Not Yet Replaced"
"Chasesa - 1000032 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 25" 21249 1 20 "Not Yet Replaced"
"Chasesa - 1000033 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 13" . 1 20 ""
"Chasesa - 1000034 - First Last (MARK-01-001)" "Neno" "Mlau" "Chasesa" "First Last 17" . 1 20 ""
"Chidakwani - 1000035 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 23" . . 2 ""
"Chidakwani - 1000036 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 23" . . 2 ""
"Chidakwani - 1000037 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 10" . . 2 ""
"Chidakwani - 1000038 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 23" . . 2 ""
"Chidakwani - 1000039 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 15" . . 2 ""
"Chidakwani - 1000040 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 15" . 1 2 ""
"Chidakwani - 1000041 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 15" . 1 2 ""
"Chidakwani - 1000042 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 1" . 1 2 ""
"Chidakwani - 1000043 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 8" 21252 . 2 "Not Yet Replaced"
"Chidakwani - 1000044 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 10" . 1 2 ""
"Chidakwani - 1000045 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 23" . . 2 ""
"Chidakwani - 1000046 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 1" 21251 . 2 "Not Yet Replaced"
"Chidakwani - 1000047 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 6" . 1 2 ""
"Chidakwani - 1000048 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 15" . . 2 ""
"Chidakwani - 1000049 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 10" . 1 2 ""
"Chidakwani - 1000050 - First Last (MARK-01-001)" "Neno" "Chek" "Chidakwani" "First Last 10" . . 2 ""
end
format %td sdate
Now open a document, and create tables within it. Here is the workflow:
- Use
levelsof
to create a local macro containing unique village names to loop through (I want a separate table within the same PDF for each village) - Begin the PDF document
- Start the loop on villages
- Add a title before the table
- Create a table based on the village name: Rather than just using the
data(varlist)
way of making a table, I am dropping all observations that do not fall under this village, then looping through each observation and writing a row on the table for each. This gives me control over the column span (the 'label' variable is a long string, while some are byte numbers, so I want different column widths and this seems like the only wayputpdf
can do what I want it to). - Add a new row to the top of the table as a header, then write the individual column cells one at a time
- Save the pdf
Here is the code:
* Get unique values of village in local vstr
levelsof village, local(vstr)
* Open the document and start the loop
set trace on // Helps to see where the code screws up
putpdf begin, page(A4) landscape margin(top, 0.25in) margin(right, 0.25in) margin(bottom,0.25in) margin(left,0.25in)
foreach village of local vstr {
preserve
local name = subinstr("`village'"," ","_",.) // These aren't impacted here, but in teh rst of my data I have spaces and apostrophes which need to go
local name = subinstr("`name'","'","_",.)
* Add a title before each table
putpdf paragraph, font("Calibri Light",14) halign(center)
putpdf text ("`village'")
* Keep only obs in this village (note 'preserve' above)
qui keep if village == "`village'"
* Get the number of observations so we can loop through row-by-row
qui count
* Start a table with N rows based on the above count
putpdf table hhs_`name' = (`r(N)',17)
* Loop through all N rows and write cell contents
forvalues i=1/`r(N)' {
putpdf table hhs_`name'(`i',1) = (substr(label[`i'],1,50)), colspan(6) // Longer string, hence colspan(6)
putpdf table hhs_`name'(`i',7) = (district[`i'])
putpdf table hhs_`name'(`i',8) = (ta[`i'])
putpdf table hhs_`name'(`i',9) = (substr(village[`i'],1,4))
putpdf table hhs_`name'(`i',10) = (cluster[`i']), colspan(3)
putpdf table hhs_`name'(`i',13) = (shopid[`i'])
putpdf table hhs_`name'(`i',14) = (coupons[`i'])
putpdf table hhs_`name'(`i',15) = (reason[`i']), colspan(2)
putpdf table hhs_`name'(`i',17) = (string(sdate[`i'],"%td_dm"))
}
* Write header row at the top of teh table
putpdf table hhs_`name'(1,.), addrows(1, before)
* The line below is where the error seems to be triggered:
putpdf table hhs_`name'(1,1) = ("Label"), colspan(6) bold bgcolor(lightgray)
*putpdf table hhs_`name'(1,7) = ("District"), bold bgcolor(lightgray)
*putpdf table hhs_`name'(1,8) = ("TA"), bold bgcolor(lightgray)
*putpdf table hhs_`name'(1,9) = ("Village"), bold bgcolor(lightgray)
*putpdf table hhs_`name'(1,10) = ("Cluster"), colspan(3) bold bgcolor(lightgray)
*putpdf table hhs_`name'(1,13) = ("Shop ID"), bold bgcolor(lightgray)
*putpdf table hhs_`name'(1,14) = ("Coupon"), bold bgcolor(lightgray)
*putpdf table hhs_`name'(1,15) = ("Reason"), colspan(2) bold bgcolor(lightgray)
*putpdf table hhs_`name'(1,17) = ("Date"), bold bgcolor(lightgray)
restore
}
* Save the document
putpdf save "Village Remaining Lists.pdf", replace
set trace off
I commented out all rows within the loop and then un-commented them one-by-one starting at the top (putpdf table hhs_name(i,1) = (substr(label...
). Originally, the file had no trouble writing a PDF. The error ("failed to add table; r(198)
") is a syntax error.
Now, if you take that line and change the option bold
to italic
(or nothing at all), the error disappears.
putpdf table hhs_`name'(1,1) = ("Label"), colspan(6) italic bgcolor(lightgray)
Using set trace on
doesn't immediately reveal where the problem actually occurs, but when you scroll up in the resulting output (when the option is set to bold
), you can see that the loop is starting again with the village "Chidakwani" before the error pops up. And the error seems to occur before the table for Chidakwani begins. So I think that the problem is happening somewhere around "Chasesa" village, and either that table is not stopping, or the Chidakwani table cannot start. And all because of the "bold" option.
The italic
workaround is sufficient for now, but I thought I would throw this out there and see if anyone wants to take a stab at figuring out what is going on.