Epson epos sdk receipt alignment issue - java

i'm currently using epson ePOS SDK for android.
i need to print the receipt that menu name align to the left and its price align to the right in the same line but it doesn't work properly,
my temporary solution is add some feed line to make its price align right, is it possible to have both text align left and right in the same line ?
(Attachments below and please ignore question mark symbols)
mPrinter.addTextAlign(Printer.ALIGN_LEFT);
mPrinter.addFeedLine(0);
textData.append(menuName);
mPrinter.addText(textData.toString());
textData.delete(0, textData.length());
mPrinter.addFeedLine(0);
//print price
mPrinter.addTextAlign(Printer.ALIGN_RIGHT);
textData.append(price + "Y" + "\n");
mPrinter.addText(textData.toString());
textData.delete(0, textData.length());
mPrinter.addFeedLine(0);

80mm is like 42 columns per line ...which can be easily padded:
mPrinter.addText(padLine(menuName, price + "¥", 42) + "\n");
the required String manipulation methods look alike:
/** utility: pads two strings to columns per line */
protected String padLine(#Nullable String partOne, #Nullable String partTwo, int columnsPerLine){
if(partOne == null) {partOne = "";}
if(partTwo == null) {partTwo = "";}
String concat;
if((partOne.length() + partTwo.length()) > columnsPerLine) {
concat = partOne + " " + partTwo;
} else {
int padding = columnsPerLine - (partOne.length() + partTwo.length());
concat = partOne + repeat(" ", padding) + partTwo;
}
return concat;
}
/** utility: string repeat */
protected String repeat(String str, int i){
return new String(new char[i]).replace("\0", str);
}
one should format the price to currency, before padding it.
to make it truly "flawless" ... when String concat exceeds length 42, then String partOne should be truncated by the excess length - and be concatenated, once again. exceeding int columnsPerLine will most likely mess up the output.

Inserting the RIGHT string in the LEFT string at an appropriate position. This is because I'm not using a feedLine provided by EPSON. Instead I'm manually adding a new line(\n) after 42(this varies according to the printer) characters.
// gap -> Number of spaces between the left and the right string
public void print(Printer epsonPrinter, String left, String right, int gap) throws Epos2Exception {
int total = 42;
// This is to give a gap between the 2 columns
for (int i = 0; i < gap; i++) {
right = " " + right;
}
// This will make sure that the right string is pushed to the right.
// If the total sum of both the strings is less than the total length(42),
// we are prepending extra spaces to the RIGHT string so that it is pushed to the right.
if ((left.length() + right.length()) < total) {
int extraSpace = total - left.length() - right.length();
for (int i = 0; i < extraSpace; i++) {
left = left + " ";
}
}
int printableSpace = total - right.length(); // printable space left for the LEFT string
//stringBuilder -> is the modified string which has RIGHT inserted in the LEFT at the appropriate position. And also contains the new line. This is the string which needs to be printed
StringBuilder stringBuilder = new StringBuilder();
// Below 2 statements make the first line of the print
stringBuilder.append(left.substring(0, Math.min(printableSpace, left.length())));
stringBuilder.append(right);
// stringBuilder now contains the first line of the print
// For appropriately printing the remaining lines of the LEFT string
for (int index = printableSpace; index < left.length(); index = index + (printableSpace)) {
stringBuilder.append(left.substring(index, Math.min(index + printableSpace, left.length())) + "\n");
}
epsonPrinter.addText(stringBuilder.toString());
}

Related

Confusing Behavior with Array Initialization -- Processing (Java)

I'm encountering some confusing behavior when trying to create an array of certain length. The length is obtained by a file read in the function getTermNums. When I try to create an array of this size, my code runs in a strange order, my i values are skewed, and the code generally doesn't run as intended. When I instead create an array of a set integer amount, the code runs as intended without error.
double[] terms;
int numTerms = getNumTerms(lines[0]);
terms = new double[numTerms];
int i = 1;
for (i = 1; i<terms.length; i++){
//terms[i] = calculateTerm(T, lines[i]);
}
the above code runs incorrectly.
double[] terms;
int numTerms = getNumTerms(lines[0]);
int myNum = 200;
terms = new double[myNum];
int i = 1;
for (i = 1; i<terms.length; i++){
//terms[i] = calculateTerm(T, lines[i]);
the above code runs correctly
int getNumTerms(String line){
int i = 60;
int j = 0;
char[] word;
word = new char[4];
int numTerms;
int numTermLen = 0;
while(new String(word).compareTo("TERM") != 0){
for (j=0; j<4; j++){
word[j] = line.charAt(i + j);
}
i++;
}
j = i - 3;
while( new Character(line.charAt(j)).equals(' ') == false){
numTermLen++;
j--;
}
j++;
println("i in here: ", i);
numTerms = Integer.parseInt(line.substring(j, j + numTermLen));
return numTerms;
}
this is the function that I'm calling to read the numterms for the size of the array in the first example that doesn't work correctly.
When I use the function call to set the size of array terms[], i starts at some value like 380, and the iteration through array lines[] begins somewhere in the middle of the array.
When I use the integer myNum to set the size of array terms[], i starts at 1, and the iteration through array lines[] begins at the first line, as intended.
Any explanation is appreciated! I'm new to coding in java and am confused by the source of this error.
Thanks in advance.
Without seeing the text it's tiresome to deduct where in your getNumTerms the error occurs.
You can make use of String's indexOf() to find the index of "TERM" and substring() to extract the String containing the integer value.
As far as I understand the ideal string would have "TERM" followed by an integer then a space character. If these items are found and the value fits within 32 bits you should be able to use something like this:
String line = "LINE START TERM-1238847 LINE END";
int getTerm(String line){
int result = Integer.MAX_VALUE;
final String SEARCH_TOKEN = "TERM";
// look for TERM token and remember index
int termIndex = line.indexOf(SEARCH_TOKEN);
// handle not found
if(termIndex < 0){
System.err.println("error: " + SEARCH_TOKEN + " not found in line");
return result;
}
// move index by the size of the token
termIndex += SEARCH_TOKEN.length();
int spaceIndex = line.indexOf(' ',termIndex);
if(spaceIndex < 0){
System.err.println("error: no SPACE found after " + SEARCH_TOKEN);
return result;
}
// chop string extracing between token end and first space encountered
String intString = line.substring(termIndex,spaceIndex);
// try to parse int handling error
try{
result = Integer.parseInt(intString);
}catch(Exception e){
System.err.println("error parsing integer from string " + intString);
e.printStackTrace();
}
return result;
}
System.out.println("parsed integer: " + getTerm(line));

Cut String by maxLines parameter, and by number of characters

I'm writing a class with a method that takes a summary string and breaks it down into a maximum number of lines (maxLines Parameter) and maximum number of characters per line (width parameter). All lines except the first line should be indented (they should start with a space character), but the second character in an indented line should not be another space (so that second space must not be included). The program should still work if you change the maxLine parameter r width.
Also, the code should check whether some special characters are in the String, like:
\' , \" , \\ , \t , \b , \r , \f , \n
How can I inspect is many spaces in String like below? If there are many spaces in the String, I want to trim them, but I don't know how to. (These underscores represent spaces.)
"9:00 John_____________________________Doe until 10 30 at Office"
9:00 Jo
_hn____
_______
_____Do
With my code, I get this result:
9:00 Jo
_hn Doe
_until 1
_0 30 at
But I want THIS this output:
9:00 Jo
_hn Doe
_until_
_10 30_
Here is my code:
public static void main(String[] args) {
String str = "9:00 John Doe until 10 30 at Office";
int width = 7;
int maxLine = 4;
List<String> lisT = new LinkedList<>(getParts(str, width, maxLine));
for (String part : lisT) {
System.out.println(part);
}
}
public static List<String> getParts(String str, int width, int maxLine) {
List<String> parts = new LinkedList<>();
int count = 0;
int len = str.length();
String indent = "";
for (int i = 0; i < len; i += width) {
parts.add(indent + str.substring(i, Math.min(len, i + width)).trim());
count++;
indent = " ";
if (count == maxLine)
break;
}
return parts;
}
So this is what you want? I really hope you don't have to implement this in something because I had to mangle this to make it work. Hopefully this is homework
public static void main(String[] args) {
String str = "9:00 John Doe until 10 30 at Office";
int width = 7;
int maxLine = 4;
List<String> lisT = new LinkedList<>(getParts(str, width, maxLine));
for (String part : lisT) {
System.out.println(part);
}
}
public static List<String> getParts(String str, int width, int maxLine){
List<String> parts = new LinkedList<>();
int endedAt = 0;
boolean firstLine = true;
boolean secondLine = true;
String indent = " ";
for (int i = 0; i < maxLine; i++) {
if(endedAt<=str.length()) {
String holder;
if(firstLine) {
holder = str.substring(endedAt, endedAt + width);
firstLine = false;
}
else {
if(secondLine){
width = width -1;
secondLine = false;
}
holder = indent + str.substring(endedAt, endedAt + width).trim();
}
parts.add(holder);
endedAt = endedAt + width;
}
}
return parts;
}
The output is
9:00 Jo
hn Doe
until
10 30
I think your rows might be too long because your width = 7 includes the indent space, so your rows have a width of 8 instead of 7. I would try replacing for (int i = 0; i < len; i += width) {... with for (int i = 1; i < len; i += width - 1) {... and add a special statement right before the for loop for the 0th row, since you do not want to indent the 0th row. Something like this:
parts.add(str.substring(0, Math.min(len, i + width)).trim());
for(...){...}
Let me know whether that seems to be the problem. If not, I can take another look. To answer your other questions:
To remove more than one space in the middle of a string, use this to replace all whitespace with exactly one space:
String result = replaceAll("\\s","");
You can remove the special characters with a regex like this:
String result = str.replaceAll("[\'\"\\\t\b\r\f\n]","");

How to retain matched sub string and replace unmatched sub strings in Java String

Hello I try to print in an array of Strings
In the following way:
Input: big = "12xy34", small = "xy" output: "** xy **"
Input: big = "" 12xt34 "", small = "xy" output: "******"
Input: big = "12xy34", small = "1" output: "1 *****"
Input: big = "12xy34xyabcxy", small = "xy" output: "** xy ** xy *** xy"
Input: big = "78abcd78cd", small = "78" output: "78 **** 78 **"
What I need to write a condition to receive as up?
public static String stars(String big, String small) {
//throw new RuntimeException("not implemented yet ");
char[] arr = big.toCharArray();
for (int i = 0; i < arr.length; i++) {
if (big.contains(small) ) {
arr[i] = '*';
}
}
String a = Arrays.toString(arr);
return big+""+a;
}
Algorithm:
Convert big and small String's to char[] array's bigC and smallC respectively
Iterate over each character of big String
At every index during iteration, identify whether there is a sub-string possible beginning current character
If there is a sub-string possibility, advance the index in big String iteration by length of small String
Otherwise, replace the character by *
Code:
public class StringRetainer {
public static void main(String args[]) {
String big[] = {"12xy34", "12xt34", "12xy34", "12xy34xyabcxy", "78abcd78cd"};
String small[] = {"xy", "xy", "1", "xy", "78"};
for(int i = 0; i < big.length & i < small.length; i++) {
System.out.println("Input: big = \"" + big[i] + "\", small = \"" + small[i] + "\" output : \"" + stars(big[i], small[i]) + "\"");
}
}
public static String stars(String big, String small) {
//String to char[] array conversions
char[] bigC = big.toCharArray();
char[] smallC = small.toCharArray();
//iterate through every character of big String and selectively replace
for(int i = 0; i < bigC.length; i++) {
//flag to determine whether small String occurs in big String
boolean possibleSubString = true;
int j = 0;
//iterate through every character of small String to determine
//the possibility of character replacement
for(; j < smallC.length && (i+j) < bigC.length; j++) {
//if there is a mismatch of at least one character in big String
if(bigC[i+j] != smallC[j]) {
//set the flag indicating sub string is not possible and break
possibleSubString = false;
break;
}
}
//if small String is part of big String,
//advance the loop index with length of small String
//replace with '*' otherwise
if(possibleSubString)
i = i+j-1;
else
bigC[i] = '*';
}
big = String.copyValueOf(bigC);
return big;
}
}
Note:
This is one possible solution (legacy way of doing)
Looks like there is no straight forward way of making this happen using built-in String/StringBuffer/StringBuilder methods

How to add string in the last foreach item?

I want to append certain string in the last item of the foreach array.
The program works perfectly fine. Given the items in the "pending" array, it should append the out value in the last item in the pending value:
String a = out + "-" + rptdate + "-";
for (String pn : pending) {
//checks if total value + pending length value is less than 160
if (a.length() + pn.length() < 160) { // < to leave room for the comma as well
if (a.length() != 0) {
if (a.length() != 14) {
a += ",";
}
}
a += pn;
} else {
resultingStrings.add(a);
a = pn;
Log.d("messages", a);
}
}
resultingStrings.add(a);
for (String r : resultingStrings) {
sendSMS(r);
}
Try simple code
int size = pending.size();
int index = 0;
for (String pn : pending) {
if(index == size - 1){
// it is last foreach => add your last string here
}
index++;
...
}
Hope this help
You could also do,
for(int i = 0; i < array.length; i++) {
if(i = (array.length - 1)) {
//this is the last element in the array
}
}
If all you need to do is grab the last element of a Collection and append some text to it then this should work.
String out = "Some value";
int lastIndex = pending.getSize() -1; // < 0 indexed
String lastItem = pending.get(lastIndex)
String newLastItem = lastItem + out; // < String concatenation
but from your snippet I don't think that's what your after because if we remove some of the magic numbers and correct the indentation, and make some assumptions about what your trying to do your left with
String a = out + "-" + rptdate + "-";
int prefixLength = a.length();
for (String pn : pending) {
//checks if total value + pending length value is less than 160
if (a.length() + pn.length() < MAX_LENGTH) { // < to leave room for the comma as well
if (a.length() > prefixLength) {
a += ",";
}
a += pn;
} else {
// have string longer than max length, so save and start a new sms.
resultingStrings.add(a);
Log.d("messages", a); // < log a before you overwrite it.
a = pn;
}
}
// DO YOU WANT TO APPEND out AS A SUFFIX TO a HERE ???
// a += out;
// but if so youll want to consider the case if a is now > MAX_LENGTH
resultingStrings.add(a); // add the last string
// send all composed strings
for (String r : resultingStrings) {
sendSMS(r);
}
I am picking your relatively new to coding so I'd suggest first you start off with some pseudo-code of what your trying to do, it can then become comments in your code. Always keep your code formatted nicely so that indents are matched, and use descriptive names for your variables, and constants.

How to print String

I have this String which I want to return but I cannot because it says that "print" cannot be resolved as a variable. This is my code:
public static String enrcyptText(String str, int shift){
int count = 0;
String[] parts = str.split("[\\W]");
for(String word : parts){
shift = shift * (count + 1) + 1;
count++;
encryptWord(word, shift);
String[] phrase = new String[]{word};
String print = String.join(" ", phrase);
}
return print;
}
any Idea?
There are several problems there.
You've declared print only within the loop body. It doesn't exist outside of it. So you need to move your String print outside the loop.
You're also assigning to it on every loop iteration, which will overwrite the previous value it had. It's unclear what you want to do instead, but you're not going to want to do that.
These two lines also don't make any sense:
String[] phrase = new String[]{word};
String print = String.join(" ", phrase);
Since there will only be one entry in phrase, you'll end up with print having the same value word had.
You seem to expect that encryptWord can modify the string passed into it. It can't.
Taking a stab at it, I'm thinking your goal is to "encrypt" individual words from a sentence, then recombine the result into a space-delimited set of encrypted words. If so, see comments:
public static String enrcyptText(String str, int shift){
int count = 0;
String[] parts = str.split("[\\W]");
// For updating the array, better to use the classic
// for loop instead of the enhanced for loop
for (int i = 0; i < parts.length; ++i){
shift = shift * (count + 1) + 1;
count++; // Could do this before previous line and remove the + 1 in (count + 1)
parts[i] = encryptWord(parts[i], shift); // See note below
}
return String.join(" ", parts);
}
Note that I'm using a return value from encryptWord. That's because strings in Java are immutable (cannot be changed), and so encryptWord can't change what we pass into it; it can only give us back a new string to use instead.
print variable has scope inside the braces.You should move the print variable outside braces to make it visible to the code.Also,since it is a local variable ,print should be initialized with a default value(in my case,it is null).The compiler will complain that print remain uninitialized(though this is not related to the main question)
public static String enrcyptText(String str, int shift){
int count = 0;
String[] parts = str.split("[\\W]");
String print = null;
for(String word : parts){
shift = shift * (count + 1) + 1;
count++;
encryptWord(word, shift);
String[] phrase = new String[]{word};
print = String.join(" ", phrase);
}
return print;
}
You have a logic error in your code: you are encrypting correctly each word but you are not building correctly the encrypted phrase. In each iteration of the loop, you are recreating the phrase when you should be adding element to the phrase array.
public static String enrcyptText(String str, int shift) {
int count = 0;
String[] parts = str.split("[\\W]");
String[] phrase = new String[parts.length]; // initialising an array containing each encrypted word
for (String word : parts) {
shift = shift * (count + 1) + 1;
count++;
String encryptedWord = encryptWord(word, shift);
phrase[count - 1] = encryptedWord; // updating the encrypted phrase array
}
return String.join(" ", phrase); // joining the phrase array
}
In this code, we are creating a phrase array before the loop. In each iteration, we update this array with the encryped word. When we have all the encrypted words, the loop terminates and we join all of the parts together.
I am also guessing that the encryptedWord actually returns the encrypted word. This method can't modify the word given as parameter.

Categories

Resources