2012-06-21 9 views
8

In meiner Anwendung verwende ich SQLite als Backend (um Daten lokal zu speichern). Ich bin in der Lage, Daten in meine Tabelle einzufügen.aber was ich will, ist, will alle meine SQLite-Daten in Excel programmgesteuert importieren.Und ich möchte nicht Server für diese app.once das Excel-Blatt ist Benutzer generieren sollte in der Lage sein, dieses Blatt zu mailen. Ist dies in iPhone möglich: Bitte helfen Sie mir.SQLite-Daten programmgesteuert in Excel exportieren

Es folgt meine Codedaten in die Tabelle einzufügen:

-(IBAction)Login 
{ 
sqlite3_stmt *stmt; 
     char *errorMsg; 
     char *update1 = "insert into Login1 values (?,?,?,?);"; 
     int x = sqlite3_prepare_v2(database, update1, -1, &stmt, nil); 

    if (x == SQLITE_OK) 
    { 
     sqlite3_bind_text(stmt, 1, NULL,-1, NULL); 
     sqlite3_bind_text(stmt, 2, [USERID UTF8String],-1, NULL); 
     sqlite3_bind_text(stmt, 3, [str1 UTF8String],-1, NULL); 
     sqlite3_bind_text(stmt, 4, [str4 UTF8String],-1, NULL); 


    } 

    if (sqlite3_step(stmt) != SQLITE_DONE) 
     NSLog(@"Error: %@",errorMsg); 
    sqlite3_finalize(stmt); 

}

Antwort

11

Für die App Ich habe die dies taten, die SQLite-Daten ziemlich groß war. Daher habe ich einen Hintergrundthread verwendet, um alle Daten in eine CSV-Datei (Komma-separierter Wert) zu exportieren, die Excel importieren kann, und dann einen Mail-Composer mit der CSV-Datei als Anhang geöffnet. Wenn Ihre Daten klein ist, können Sie nicht einen Hintergrund-Thread verwenden müssen:

- (IBAction) export: (id) sender 
{  
    // in my full code, I start a UIActivityIndicator spinning and show a 
    // message that the app is "Exporting ..." 

    [self performSelectorInBackground: @selector(exportImpl) withObject: nil]; 
} 

Hier ist exportImpl

- (void) exportImpl 
{ 
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 

    NSArray* documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSSystemDomainMask, YES); 
    NSString* documentsDir = [documentPaths objectAtIndex:0]; 
    NSString* csvPath = [documentsDir stringByAppendingPathComponent: @"export.csv"]; 

    // TODO: mutex lock? 
    [sqliteDb exportCsv: csvPath]; 

    [pool release]; 

    // mail is graphical and must be run on UI thread 
    [self performSelectorOnMainThread: @selector(mail:) withObject: csvPath waitUntilDone: NO]; 
} 

- (void) mail: (NSString*) filePath 
{ 
    // here I stop animating the UIActivityIndicator 

    // http://howtomakeiphoneapps.com/home/2009/7/14/how-to-make-your-iphone-app-send-email-with-attachments.html 
    BOOL success = NO; 
    if ([MFMailComposeViewController canSendMail]) { 
     // TODO: autorelease pool needed ? 
     NSData* database = [NSData dataWithContentsOfFile: filePath]; 

     if (database != nil) { 
      MFMailComposeViewController* picker = [[MFMailComposeViewController alloc] init]; 
      picker.mailComposeDelegate = self; 
      [picker setSubject:[NSString stringWithFormat: @"%@ %@", [[UIDevice currentDevice] model], [filePath lastPathComponent]]]; 

      NSString* filename = [filePath lastPathComponent]; 
      [picker addAttachmentData: database mimeType:@"application/octet-stream" fileName: filename]; 
      NSString* emailBody = @"Attached is the SQLite data from my iOS device."; 
      [picker setMessageBody:emailBody isHTML:YES]; 

      [self presentModalViewController:picker animated:YES]; 
      success = YES; 
      [picker release]; 
     } 
    } 

    if (!success) { 
     UIAlertView* warning = [[UIAlertView alloc] initWithTitle: @"Error" 
                  message: @"Unable to send attachment!" 
                 delegate: self 
               cancelButtonTitle: @"Ok" 
               otherButtonTitles: nil]; 
     [warning show]; 
     [warning release]; 
    } 
} 

Und dann, ich habe eine Klasse, die meine SQLite alle Daten kapselt. Diese Klasse ist die einzige, die SQLite-Aufrufe durchführt. In dieser Klasse habe ich eine Methode zum Exportieren von Daten in eine CSV-Datei in der Caches Verzeichnis meiner App. Die Variable sqliteDb im obigen Code ist eine Instanz dieser Klasse. Hier ist die Methode zum Exportieren von Daten:

-(void) exportCsv: (NSString*) filename 
{ 
    // We record this filename, because the app deletes it on exit 
    self.tempFile = filename; 

    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 
    // Setup the database object 
    sqlite3* database; 

    // Open the database from the users filessytem 
    if (sqlite3_open([self.databasePath UTF8String], &database) == SQLITE_OK) 
    { 
     [self createTempFile: filename]; 
     NSOutputStream* output = [[NSOutputStream alloc] initToFileAtPath: filename append: YES]; 
     [output open]; 
     if (![output hasSpaceAvailable]) { 
      NSLog(@"No space available in %@", filename); 
      // TODO: UIAlertView? 
     } else { 
      NSString* header = @"Source,Time,Latitude,Longitude,Accuracy\n"; 
      NSInteger result = [output write: [header UTF8String] maxLength: [header length]]; 
      if (result <= 0) { 
       NSLog(@"exportCsv encountered error=%d from header write", result); 
      } 

      BOOL errorLogged = NO; 
      NSString* sqlStatement = @"select timestamp,latitude,longitude,horizontalAccuracy from my_sqlite_table"; 

      // Setup the SQL Statement and compile it for faster access 
      sqlite3_stmt* compiledStatement; 
      if (sqlite3_prepare_v2(database, [sqlStatement UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK) 
      { 
       // Loop through the results and write them to the CSV file 
       while (sqlite3_step(compiledStatement) == SQLITE_ROW) { 
        // Read the data from the result row 
        NSInteger secondsSinceReferenceDate = (NSInteger)sqlite3_column_double(compiledStatement, 0); 
        float lat = (float)sqlite3_column_double(compiledStatement, 1); 
        float lon = (float)sqlite3_column_double(compiledStatement, 2); 
        float accuracy = (float)sqlite3_column_double(compiledStatement, 3); 

        if (lat != 0 && lon != 0) { 
         NSDate* timestamp = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: secondsSinceReferenceDate]; 
         NSString* line = [[NSString alloc] initWithFormat: @"%@,%@,%f,%f,%d\n", 
             table, [dateFormatter stringFromDate: timestamp], lat, lon, (NSInteger)accuracy]; 
         result = [output write: [line UTF8String] maxLength: [line length]]; 
         if (!errorLogged && (result <= 0)) { 
          NSLog(@"exportCsv write returned %d", result); 
          errorLogged = YES; 
         } 
         [line release]; 
         [timestamp release]; 
        } 
        // Release the compiled statement from memory 
        sqlite3_finalize(compiledStatement); 
       } 
      } 
     } 
     [output close]; 
     [output release]; 
    } 

    sqlite3_close(database); 
    [pool release]; 
} 

-(void) createTempFile: (NSString*) filename { 
    NSFileManager* fileSystem = [NSFileManager defaultManager]; 
    [fileSystem removeItemAtPath: filename error: nil]; 

    NSMutableDictionary* attributes = [[NSMutableDictionary alloc] init]; 
    NSNumber* permission = [NSNumber numberWithLong: 0640]; 
    [attributes setObject: permission forKey: NSFilePosixPermissions]; 
    if (![fileSystem createFileAtPath: filename contents: nil attributes: attributes]) { 
     NSLog(@"Unable to create temp file for exporting CSV."); 
     // TODO: UIAlertView? 
    } 
    [attributes release]; 
} 

Mein Code exportiert eine Datenbank mit Standortinformationen. Offensichtlich müssen Sie innerhalb von exportCsv meine SQLite-Aufrufe durch solche ersetzen, die für Ihren Datenbankinhalt geeignet sind.

Außerdem speichert der Code die Daten in einer temporären Datei. Wahrscheinlich möchten Sie entscheiden, wann diese temporären Dateien gelöscht werden sollen.

Offensichtlich wurde dieser Code geschrieben, bevor ARC verfügbar war. Passen Sie wie erforderlich an.

Verwandte Themen