【问题标题】:Export SQLite data to Excel in iOS programmatically以编程方式将 SQLite 数据导出到 iOS 中的 Excel
【发布时间】:2012-06-23 09:03:18
【问题描述】:

在我的应用程序中,我使用 sqlite 作为后端(在本地存储数据)。 我能够将数据插入到我的表中。但我想要做的是,想以编程方式将我所有的 sqlite 数据导入到 excel 中。我不想为这个应用程序使用服务器。一旦生成了 excel 表,用户应该能够邮寄那张纸。 这在 iPhone 中是否可行: 请帮帮我。

以下是我将数据插入表格的代码:

-(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);

}

【问题讨论】:

    标签: iphone objective-c ios sqlite


    【解决方案1】:

    对于我这样做的应用程序,SQLite 数据相当大。因此,我使用后台线程将所有数据导出到 Excel 可以导入的 CSV(逗号分隔值)文件,然后以 CSV 文件作为附件打开邮件编写器。如果您的数据很小,您可能不需要使用后台线程:

    - (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];
    }
    

    这里是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];
        }
    }
    

    然后,我有一个封装我所有 SQLite 数据的类。这个类是唯一一个进行 sqlite 调用的类。在这个类中,我有一种方法可以将数据导出到我的应用程序 caches 目录中的 CSV 文件中。上面代码中的变量sqliteDb就是这个类的一个实例。导出数据的方法如下:

    -(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];
    }
    

    我的代码正在导出位置信息数据库。显然,在 exportCsv 中,您需要将我的 sqlite 调用替换为适合您的数据库内容的调用。

    此外,代码将数据存储在临时文件中。您可能需要决定何时清除这些临时文件。

    显然,此代码是在 ARC 可用之前编写的。根据需要进行调整。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多