File Coverage

blib/lib/App/CSVUtils/csv_sum.pm
Criterion Covered Total %
statement 14 14 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 19 19 100.0


line stmt bran cond sub pod time code
1             package App::CSVUtils::csv_sum;
2              
3 1     1   7436 use 5.010001;
  1         4  
4 1     1   5 use strict;
  1         2  
  1         20  
5 1     1   5 use warnings;
  1         3  
  1         65  
6              
7             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
8             our $DATE = '2023-04-01'; # DATE
9             our $DIST = 'App-CSVUtils'; # DIST
10             our $VERSION = '1.024'; # VERSION
11              
12 1         196 use App::CSVUtils qw(
13             gen_csv_util
14 1     1   9 );
  1         2  
15              
16             gen_csv_util(
17             name => 'csv_sum',
18             summary => 'Output a summary row which are arithmetic sum of data rows',
19             description => <<'_',
20              
21             Non-numbers will be assumed to be 0.
22              
23             Example:
24              
25             # students.csv
26             name,score
27             andi,130
28             budi,120
29             chandra,120
30             dudi,120
31              
32             % csv-sum students.csv
33             name,score
34             0,490
35              
36             % csv-sum students.csv --with-data-row
37             name,score
38             andi,130
39             budi,120
40             chandra,120
41             dudi,120
42             0,12.25
43              
44             _
45             add_args => {
46             %App::CSVUtils::argspecopt_with_data_rows,
47             },
48              
49             tags => ['category:summarizing'],
50              
51             on_input_header_row => sub {
52             my $r = shift;
53              
54             # we add this key to the stash
55             $r->{summary_row} = [map {0} @{$r->{input_fields}}];
56             $r->{row_count} = 0;
57              
58             # because input_* will be cleared by the time of after_read_input,
59             # we save and set it now
60             $r->{output_fields} = $r->{input_fields};
61             },
62              
63             on_input_data_row => sub {
64             my $r = shift;
65              
66             for my $j (0 .. $#{ $r->{input_fields} }) {
67 1     1   6 no warnings 'numeric', 'uninitialized';
  1         2  
  1         162  
68             $r->{summary_row}[$j] += $r->{input_row}[$j]+0;
69             }
70             $r->{code_print_row}->($r->{input_row}) if $r->{util_args}{with_data_rows};
71             $r->{row_count}++;
72             },
73              
74             after_read_input => sub {
75             my $r = shift;
76              
77             $r->{code_print_row}->($r->{summary_row});
78             },
79             );
80              
81             1;
82             # ABSTRACT: Output a summary row which are arithmetic sum of data rows
83              
84             __END__
85              
86             =pod
87              
88             =encoding UTF-8
89              
90             =head1 NAME
91              
92             App::CSVUtils::csv_sum - Output a summary row which are arithmetic sum of data rows
93              
94             =head1 VERSION
95              
96             This document describes version 1.024 of App::CSVUtils::csv_sum (from Perl distribution App-CSVUtils), released on 2023-04-01.
97              
98             =head1 FUNCTIONS
99              
100              
101             =head2 csv_sum
102              
103             Usage:
104              
105             csv_sum(%args) -> [$status_code, $reason, $payload, \%result_meta]
106              
107             Output a summary row which are arithmetic sum of data rows.
108              
109             Non-numbers will be assumed to be 0.
110              
111             Example:
112              
113             # students.csv
114             name,score
115             andi,130
116             budi,120
117             chandra,120
118             dudi,120
119            
120             % csv-sum students.csv
121             name,score
122             0,490
123            
124             % csv-sum students.csv --with-data-row
125             name,score
126             andi,130
127             budi,120
128             chandra,120
129             dudi,120
130             0,12.25
131              
132             This function is not exported.
133              
134             Arguments ('*' denotes required arguments):
135              
136             =over 4
137              
138             =item * B<inplace> => I<true>
139              
140             Output to the same file as input.
141              
142             Normally, you output to a different file than input. If you try to output to the
143             same file (C<-o INPUT.csv -O>) you will clobber the input file; thus the utility
144             prevents you from doing it. However, with this C<--inplace> option, you can
145             output to the same file. Like perl's C<-i> option, this will first output to a
146             temporary file in the same directory as the input file then rename to the final
147             file at the end. You cannot specify output file (C<-o>) when using this option,
148             but you can specify backup extension with C<-b> option.
149              
150             Some caveats:
151              
152             =over
153              
154             =item * if input file is a symbolic link, it will be replaced with a regular file;
155              
156             =item * renaming (implemented using C<rename()>) can fail if input filename is too long;
157              
158             =item * value specified in C<-b> is currently not checked for acceptable characters;
159              
160             =item * things can also fail if permissions are restrictive;
161              
162             =back
163              
164             =item * B<inplace_backup_ext> => I<str> (default: "")
165              
166             Extension to add for backup of input file.
167              
168             In inplace mode (C<--inplace>), if this option is set to a non-empty string, will
169             rename the input file using this extension as a backup. The old existing backup
170             will be overwritten, if any.
171              
172             =item * B<input_escape_char> => I<str>
173              
174             Specify character to escape value in field in input CSV, will be passed to Text::CSV_XS.
175              
176             Defaults to C<\\> (backslash). Overrides C<--input-tsv> option.
177              
178             =item * B<input_filename> => I<filename> (default: "-")
179              
180             Input CSV file.
181              
182             Use C<-> to read from stdin.
183              
184             Encoding of input file is assumed to be UTF-8.
185              
186             =item * B<input_header> => I<bool> (default: 1)
187              
188             Specify whether input CSV has a header row.
189              
190             By default, the first row of the input CSV will be assumed to contain field
191             names (and the second row contains the first data row). When you declare that
192             input CSV does not have header row (C<--no-input-header>), the first row of the
193             CSV is assumed to contain the first data row. Fields will be named C<field1>,
194             C<field2>, and so on.
195              
196             =item * B<input_quote_char> => I<str>
197              
198             Specify field quote character in input CSV, will be passed to Text::CSV_XS.
199              
200             Defaults to C<"> (double quote). Overrides C<--input-tsv> option.
201              
202             =item * B<input_sep_char> => I<str>
203              
204             Specify field separator character in input CSV, will be passed to Text::CSV_XS.
205              
206             Defaults to C<,> (comma). Overrides C<--input-tsv> option.
207              
208             =item * B<input_tsv> => I<true>
209              
210             Inform that input file is in TSV (tab-separated) format instead of CSV.
211              
212             Overriden by C<--input-sep-char>, C<--input-quote-char>, C<--input-escape-char>
213             options. If one of those options is specified, then C<--input-tsv> will be
214             ignored.
215              
216             =item * B<output_always_quote> => I<bool> (default: 0)
217              
218             Whether to always quote values.
219              
220             When set to false (the default), values are quoted only when necessary:
221              
222             field1,field2,"field three contains comma (,)",field4
223              
224             When set to true, then all values will be quoted:
225              
226             "field1","field2","field three contains comma (,)","field4"
227              
228             =item * B<output_escape_char> => I<str>
229              
230             Specify character to escape value in field in output CSV, will be passed to Text::CSV_XS.
231              
232             This is like C<--input-escape-char> option but for output instead of input.
233              
234             Defaults to C<\\> (backslash). Overrides C<--output-tsv> option.
235              
236             =item * B<output_filename> => I<filename>
237              
238             Output filename.
239              
240             Use C<-> to output to stdout (the default if you don't specify this option).
241              
242             Encoding of output file is assumed to be UTF-8.
243              
244             =item * B<output_header> => I<bool>
245              
246             Whether output CSV should have a header row.
247              
248             By default, a header row will be output I<if> input CSV has header row. Under
249             C<--output-header>, a header row will be output even if input CSV does not have
250             header row (value will be something like "col0,col1,..."). Under
251             C<--no-output-header>, header row will I<not> be printed even if input CSV has
252             header row. So this option can be used to unconditionally add or remove header
253             row.
254              
255             =item * B<output_quote_char> => I<str>
256              
257             Specify field quote character in output CSV, will be passed to Text::CSV_XS.
258              
259             This is like C<--input-quote-char> option but for output instead of input.
260              
261             Defaults to C<"> (double quote). Overrides C<--output-tsv> option.
262              
263             =item * B<output_quote_empty> => I<bool> (default: 0)
264              
265             Whether to quote empty values.
266              
267             When set to false (the default), empty values are not quoted:
268              
269             field1,field2,,field4
270              
271             When set to true, then empty values will be quoted:
272              
273             field1,field2,"",field4
274              
275             =item * B<output_sep_char> => I<str>
276              
277             Specify field separator character in output CSV, will be passed to Text::CSV_XS.
278              
279             This is like C<--input-sep-char> option but for output instead of input.
280              
281             Defaults to C<,> (comma). Overrides C<--output-tsv> option.
282              
283             =item * B<output_tsv> => I<bool>
284              
285             Inform that output file is TSV (tab-separated) format instead of CSV.
286              
287             This is like C<--input-tsv> option but for output instead of input.
288              
289             Overriden by C<--output-sep-char>, C<--output-quote-char>, C<--output-escape-char>
290             options. If one of those options is specified, then C<--output-tsv> will be
291             ignored.
292              
293             =item * B<overwrite> => I<bool>
294              
295             Whether to override existing output file.
296              
297             =item * B<with_data_rows> => I<bool>
298              
299             Whether to also output data rows.
300              
301              
302             =back
303              
304             Returns an enveloped result (an array).
305              
306             First element ($status_code) is an integer containing HTTP-like status code
307             (200 means OK, 4xx caller error, 5xx function error). Second element
308             ($reason) is a string containing error message, or something like "OK" if status is
309             200. Third element ($payload) is the actual result, but usually not present when enveloped result is an error response ($status_code is not 2xx). Fourth
310             element (%result_meta) is called result metadata and is optional, a hash
311             that contains extra information, much like how HTTP response headers provide additional metadata.
312              
313             Return value: (any)
314              
315             =head1 HOMEPAGE
316              
317             Please visit the project's homepage at L<https://metacpan.org/release/App-CSVUtils>.
318              
319             =head1 SOURCE
320              
321             Source repository is at L<https://github.com/perlancar/perl-App-CSVUtils>.
322              
323             =head1 AUTHOR
324              
325             perlancar <perlancar@cpan.org>
326              
327             =head1 CONTRIBUTING
328              
329              
330             To contribute, you can send patches by email/via RT, or send pull requests on
331             GitHub.
332              
333             Most of the time, you don't need to build the distribution yourself. You can
334             simply modify the code, then test via:
335              
336             % prove -l
337              
338             If you want to build the distribution (e.g. to try to install it locally on your
339             system), you can install L<Dist::Zilla>,
340             L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
341             L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
342             Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
343             that are considered a bug and can be reported to me.
344              
345             =head1 COPYRIGHT AND LICENSE
346              
347             This software is copyright (c) 2023, 2022, 2021, 2020, 2019, 2018, 2017, 2016 by perlancar <perlancar@cpan.org>.
348              
349             This is free software; you can redistribute it and/or modify it under
350             the same terms as the Perl 5 programming language system itself.
351              
352             =head1 BUGS
353              
354             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-CSVUtils>
355              
356             When submitting a bug or request, please include a test-file or a
357             patch to an existing test-file that illustrates the bug or desired
358             feature.
359              
360             =cut