2017-10-09 5 views
2

Je suis un débutant complet dans le monde du codage et j'essaie d'utiliser IText pour générer des PDF à partir de mon application. J'ai réussi à créer des PDF de base avec du texte, une table, etc. Maintenant, je veux récupérer des données d'une base de données déjà créée et non vide. J'ai regardé de nombreux sujets sur StackOverflow et sur Internet sans être capable de faire fonctionner ça.Afficher le résultat d'une base de données SQLite en PDF en utilisant Itext

Toute aide sera la bienvenue

S'il vous plaît laissez-moi savoir si vous avez besoin d'autre chose et merci d'avance!

Voici mon code:

ReportActivity

public class ReportActivity extends AppCompatActivity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_report); 
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 
    //getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
} 

public void onClick_report(View view) { 
    try { 
     createPdf(); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (DocumentException e) { 
     e.printStackTrace(); 
    } 

} 

private void createPdf() throws FileNotFoundException, DocumentException { 

    File pdfFolder = new File(getExternalFilesDir("report"), "report"); 
    Date date = new Date(); 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(date); 
    File myFile = new File(pdfFolder + timeStamp + ".pdf"); 
    OutputStream output = new FileOutputStream(myFile); 

    DatabaseHandler db = new DatabaseHandler(getApplicationContext()); 
    Cursor cursor = db.getSepficItem(); 

    //Step 1 
    Document document = new Document(); 

    //Step 2 
    PdfWriter.getInstance(document, output); 

    //Step 3 
    document.open(); 

    //Step 4 Add content 

    PdfPTable table = new PdfPTable(6); 

    table.addCell("id col"); 
    table.addCell("day col"); 
    table.addCell("month col"); 
    table.addCell("Year col"); 
    table.addCell("type col"); 
    table.addCell("amount col"); 
    table.addCell("comment col"); 
    table.addCell("photo col"); 
    table.addCell("cust col"); 

    cursor.moveToFirst(); 
    int count = cursor.getCount(); 

    for (int j = 0; j < count; j++) 
    { 
     table.addCell(cursor.getString(cursor.getColumnIndex("id"))); 
     table.addCell(cursor.getString(cursor.getColumnIndex("day"))); 
     table.addCell(cursor.getString(cursor.getColumnIndex("month"))); 
     table.addCell(cursor.getString(cursor.getColumnIndex("year"))); 
     table.addCell(cursor.getString(cursor.getColumnIndex("type"))); 
     table.addCell(cursor.getString(cursor.getColumnIndex("amount"))); 
     table.addCell(cursor.getString(cursor.getColumnIndex("comment"))); 
     table.addCell(cursor.getString(cursor.getColumnIndex("photo"))); 
     table.addCell(cursor.getString(cursor.getColumnIndex("customername"))); 

     cursor.moveToNext(); 
    } 

    //Step 5: Close the document 
    document.close(); 
} 

DataBaseHelper:

public class DatabaseHandler extends SQLiteOpenHelper { 
private static final int DATABASE_VERSION = 18; 
private static final String DATABASE_NAME = "ExpenseNote"; 

//Table Customer 
private static final String TABLE_CUST = "Customer"; 
private static final String CUST_ID = "id"; 
private static final String CUST_NAME = "name"; 

//Table Expense 
private static final String TABLE_EXPENSE = "Expense"; 
private static final String EXPENS_ID = "id"; 
private static final String EXPENS_DAY = "day"; 
private static final String EXPENS_MONTH = "month"; 
private static final String EXPENS_YEAR = "year"; 
private static final String EXPENS_TYPE = "type"; 
private static final String EXPENS_AMOUNT = "amount"; 
private static final String EXPENS_COMMENT = "comment"; 
private static final String EXPENS_PHOTO = "photo"; 
private static final String EXPENS_CUST = "customername"; 


public DatabaseHandler(Context context) { 
    super(context, DATABASE_NAME, null, DATABASE_VERSION); 
} 

// Creating Tables 
@Override 
public void onCreate(SQLiteDatabase db) { 
    // Category table create query 
    String CREATE_ITEM_TABLE = "CREATE TABLE IF NOT EXISTS " 
      + TABLE_CUST + "(" 
      + CUST_ID + " integer primary key," 
      + CUST_NAME + " text not null)"; 
    db.execSQL(CREATE_ITEM_TABLE); 

    String CREATE_EXPENSE_TABLE = "CREATE TABLE IF NOT EXISTS " 
      + TABLE_EXPENSE + "(" 
      + EXPENS_ID + " integer PRIMARY KEY," 
      + EXPENS_DAY + " integer," 
      + EXPENS_MONTH + " integer," 
      + EXPENS_YEAR + " integer," 
      + EXPENS_TYPE + " text," 
      + EXPENS_AMOUNT + " real," 
      + EXPENS_COMMENT + " text," 
      + EXPENS_PHOTO + " text," 
      + EXPENS_CUST + " text)"; 
    // + " FOREIGN KEY (" + CUST_ID + ") REFERENCES " + TABLE_CUST + "(" + CUST_ID + "));"; 
    db.execSQL(CREATE_EXPENSE_TABLE); 

} 


public Cursor getSepficItem(){ 
    // Select All Query 
    SQLiteDatabase db = this.getReadableDatabase(); 
    String q = "SELECT * FROM Expense"; 
    Cursor mCursor = db.rawQuery(q, null); 
    // closing connection 
    mCursor.close(); 
    db.close(); 

    // returning customer 
    return mCursor; 
} 

Logcat:

FATAL EXCEPTION: main java.lang.IllegalStateException: Could not execute method for android:onClick 
     at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293) 
     at android.view.View.performClick(View.java:5610) 
     at android.view.View$PerformClick.run(View.java:22265) 
     at android.os.Handler.handleCallback(Handler.java:751) 
     at android.os.Handler.dispatchMessage(Handler.java:95) 
     at android.os.Looper.loop(Looper.java:154) 
     at android.app.ActivityThread.main(ActivityThread.java:6077) 
     at java.lang.reflect.Method.invoke(Native Method) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) 
    Caused by: java.lang.reflect.InvocationTargetException 
     at java.lang.reflect.Method.invoke(Native Method) 
     at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
     at android.view.View.performClick(View.java:5610)  
     at android.view.View$PerformClick.run(View.java:22265)  
     at android.os.Handler.handleCallback(Handler.java:751)  
     at android.os.Handler.dispatchMessage(Handler.java:95)  
     at android.os.Looper.loop(Looper.java:154)  
     at android.app.ActivityThread.main(ActivityThread.java:6077)  
     at java.lang.reflect.Method.invoke(Native Method)  
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)  
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)  
    Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteQuery: SELECT * FROM Expense 
     at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55) 
     at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:58) 
     at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143) 
     at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132) 
     at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:219) 
     at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:258) 
     at lu.digitalsecurity.expensenote.ReportActivity.createPdf(ReportActivity.java:89) 
     at lu.digitalsecurity.expensenote.ReportActivity.onClick_report(ReportActivity.java:35) 
     at java.lang.reflect.Method.invoke(Native Method)  
     at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)  
     at android.view.View.performClick(View.java:5610)  
     at android.view.View$PerformClick.run(View.java:22265)  
     at android.os.Handler.handleCallback(Handler.java:751)  
     at android.os.Handler.dispatchMessage(Handler.java:95)  
     at android.os.Looper.loop(Looper.java:154)  
     at android.app.ActivityThread.main(ActivityThread.java:6077)  
     at java.lang.reflect.Method.invoke(Native Method)  
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)  
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)  

Modifier comme demandé:

fichier XML (seulement un simple bouton pour le moment):

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
app:layout_behavior="@string/appbar_scrolling_view_behavior" 
tools:context=".ReportActivity" 
tools:showIn="@layout/activity_report"> 
<Button 
    android:id="@+id/button" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Button" 
    app:layout_constraintTop_toTopOf="parent" 
    android:layout_marginTop="45dp" 
    android:layout_marginLeft="50dp" 
    app:layout_constraintLeft_toLeftOf="parent" 
    android:layout_marginRight="50dp" 
    app:layout_constraintRight_toRightOf="parent" 
    android:onClick="onClick_report"/> 

+0

publier votre XML d'activité et le code d'activité – akhilesh0707

+0

commentaire 'mCursor.close();' getSepficItem() – akhilesh0707

+0

Vous ne devez pas fermer un curseur, ni la base de données jusqu'à ce que vous avez terminé avec le curseur autre (bien vous savez maintenant). enlever les 2 lignes 'mCursor.close(); db.close(); 'de la méthode' getSepficItem'. – MikeT

Répondre

2

Eh bien en fait la pile ne vous indique où l'erreur est: "tentative de rouvrir un objet déjà fermé ". Quand vous faites mCursor.close(), vous dites que le système "Je ne l'utiliserai plus, vous pouvez libérer des ressources".

à mon humble avis, vous devriez avoir une frais de classe, ressemblant à:

public class Expense { 
    private int id, day, month, year; 
    private String type; 
    // and so on... 
    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 
    // Other getters/setters 

} 

Et votre méthode getSepficItem() doit retourne une liste:

public List<Expense> getSepficItem() { 
    List<Expense> result = new ArrayList(); 
    // Select All Query 
    SQLiteDatabase db = this.getReadableDatabase(); 
    String q = "SELECT * FROM Expense"; 
    Cursor mCursor = db.rawQuery(q, null); 
    if (cursor.moveToFirst()) { 
     do { 
      Expense expense = new Expense(); 
      expense.setId(Integer.parseInt(cursor.getString(0))); 
      // etc... 
      expense.setType(cursor.getString(2)); 
      // etc... 
      result.add(contact); 
     } while (cursor.moveToNext()); 
    } 
    mCursor.close(); 
    db.close(); 
    return result; 
} 

Le la méthode qui génère le PDF doit utiliser des frais , et pas le curseur.

S'il vous plaît noter que ce n'est pas une solution complète de votre problème spécifique, plutôt un indice sur la façon d'organiser votre code.

adapter enfin la création de pdf:

createPdf() { 

    for (Expense expense : db.getSepficItem()) { 
    // .. 
    table.addCell(expense.getId()); 
    } 
} 
+0

Eh bien c'est plus facile que de traiter avec Cursor ... Voir ma mise à jour réponse. – Benoit

+0

Merci pour vos conseils, mais maintenant je n'ai aucune idée sur la façon dont je peux utiliser cela pour résoudre mon problème. Puis-je vous demander de m'aider avec plus de détails à ce sujet? – Pyr0

+0

Eh bien, je viens de mettre à jour ma réponse. Encore une fois ce n'est pas une solution complète, seulement une indication dans la bonne direction. – Benoit